1. 程式人生 > >LeetCode 334 Increasing Triplet

LeetCode 334 Increasing Triplet

這個題是說看一個沒有排序的數組裡面有沒有三個遞增的子序列,也即:

Return true if there exists i, j, k 
such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false.

大家都知道這個題有很多解法,然而題主喪心病狂地說要O(n)的時間複雜度和O(1)的空間複雜度。

我當時考慮的是找三個遞增的數,中間那個數比較重要,所以我們可以遍歷該陣列,檢查每個元素是不是遞增序列的中間那個數,假設我們叫它為p。

那要成為p有什麼條件呢?召喚畫面感。

p把整個陣列劃分成兩部分。如果在前面有比p小的,且在後面有比p大的,那麼成了。反之,(1)如果前面最小的數都比p大,(2)或者後面最大的數都比p小,那麼p肯定不是”中間那個數“,對吧?

那麼我們從第二個數開始,檢查它是不是p。滿足(1),其實可以通過求一個數組最小值來做到,從左到右,如果一個元素是當前最小的,那麼肯定就滿足(1)了。我們就可以把它從數組裡面排除了。同理,從右到左,如果一個元素是當前最大的,那麼滿足(2)了,排除完了還有剩下的,就是說明有戲了嘛。但是怎麼排除呢。。。?人家又不許有臨時陣列啊。。。O(1)的時間複雜度啊。只有耍機靈了。直接在數組裡面吧排除了的數設定成一個invalid number...OMG。瑪德智障啊。。。

       bool increasingTriplet(vector<int>& nums)
        {   

            vector
<int>::iterator it; int min = INT_MAX; for(it = nums.begin(); it < nums.end(); it++) { if(*it <= min) { min = *it; *it = INT_MIN;//i feel there should not be such element... } } vector
<int>::reverse_iterator rit = nums.rbegin(); int max = INT_MIN; for(; rit < nums.rend(); rit++) { if (*rit >= max && *rit != INT_MIN) { max = *rit; } else if (*rit != INT_MIN){ return true; } } return false; }

捂臉。。居然過了。

但是時間就。。。

於是好奇的貓看了下討論。天。。好簡單的答案。

if (numsSize < 3) return false;
int l = nums[0], m = 0x7fffffff;
for (int i = 1; i < numsSize; i++) {
    int a = nums[i];
    if (a <= l) l = a;
    else if (a < m) m = a;
    else if (a > m) return true;
}
return false;

你萌看懂了伐?

其實他也認為”中間“那個數是很重要的。所以就是用m來代替。m之前始終有個比他小的數(l,或曾經的l)。所以如果當前遍歷到的元素大於了m,那麼就return true。