mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
2.3 KiB
2.3 KiB
334. Increasing Triplet Subsequence
思路
这道题让我们求一个无序数组中是否包含一个三个元素的递增子序列,并要求时间复杂度O(n)空间复杂度O(1)。
时间复杂度O(n)很好满足,但是空间复杂度要想O(1)就有点难想了。
因为我们可以用两个dp数组dp1和dp2(可以优化成只用一个dp数组),dp1[i]和dp2[i]分别代表nums[i]前面的最小值和后面的最大值,
然后再判断是否存在dp1[i] < nums[i] < dp2[i]就可以了
,这种方法时间复杂度是满足的,但是空间复杂度为O(n),不满足题意。
我们从前往后遍历nums数组,定义
- m2为到目前为止最有可能构成三元递增序列第二个元素的候选者,即需满足m2尽可能小且在m2之前存在比m2小的数。
这样定义之后,如果我们一旦遇到某个数nums[i]比m2大,说明找到了三元递增序列。问题关键在于如何维持m2。
为此,我们需要再
- 定义一个数m1表示到目前为止最有可能构成三元递增序列第一个元素的候选者,也即到目前为止的最小值;
需要注意的是,前面说了在m2之前一定存在比m2小的数,但这个数不一定是m1!!!,m1可能是m2之后的数,例如nums=[3,4,1,6],当遍历完1后m2=4而m1=1,网上绝大多数博客都没提及这一点。
更新m1和m2的方式为:
- 初始时设置
m1 = m2 = INT_MAX
; - 若
nums[i] <= m1
, 说明遇到了更小的值,更新m1 = nums[1]
即可(这里的更新就是在m2前且比m2小的数不一定就是m1的原因); - 否则,即
nums[i] > m1
,说明在nums[i]之前肯定有一个数(就是当前的m1)比nums[i]小,又因为我们想m2尽可能小,所以如果nums[i] <= m2
,应更新m2 = nums[i]
; - 否则说明
nums[i] > m2
,找到了递增子序列,return true。
这样空间复杂度就为O(1)了,上述思路还可以推广到子序列长度为4、5...无非就是多开辟几个mx罢了。
C++
public:
bool increasingTriplet(vector<int>& nums) {
int m1 = INT_MAX, m2 = INT_MAX;
for(int num: nums){
if(num <= m1) m1 = num;
else if(num <= m2) m2 = num;
else return true;
}
return false;
}
};