diff --git a/solutions/334. Increasing Triplet Subsequence.md b/solutions/334. Increasing Triplet Subsequence.md index 62d8a8e..a769e2c 100644 --- a/solutions/334. Increasing Triplet Subsequence.md +++ b/solutions/334. Increasing Triplet Subsequence.md @@ -7,7 +7,39 @@ 因为我们可以用两个dp数组dp1和dp2(可以优化成只用一个dp数组),dp1[i]和dp2[i]分别代表nums[i]前面的最小值和后面的最大值, 然后再判断是否存在`dp1[i] < nums[i] < dp2[i]就可以了`,这种方法时间复杂度是满足的,但是空间复杂度为O(n),不满足题意。 -我们定义m2为到目前为止最有可能构成三元递增序列第二个元素的候选者,即需满足m2尽可能小且在m2之前存在比m2小的数。 +我们从前往后遍历nums数组,定义 +* m2为到目前为止最有可能构成三元递增序列第二个元素的候选者,即需满足m2尽可能小且在m2之前存在比m2小的数。 + 这样定义之后,如果我们一旦遇到某个数nums[i]比m2大,说明找到了三元递增序列。问题关键在于如何维持m2。 -为此,我们需要再定义一个数m1为到目前为止最有可能构成三元递增序列第一个元素的候选者,也即到目前为止的最小值;更新m1和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++ +``` C++ +public: + bool increasingTriplet(vector& 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; + } +}; +``` +