随笔- 40  评论- 45  文章- 0 

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。

posted on 2016-02-28 19:46  lichen782  阅读(...)  评论(...编辑  收藏