友情支持
如果您觉得这个笔记对您有所帮助,看在D瓜哥码这么多字的辛苦上,请友情支持一下,D瓜哥感激不尽,😜
有些打赏的朋友希望可以加个好友,欢迎关注D 瓜哥的微信公众号,这样就可以通过公众号的回复直接给我发信息。
公众号的微信号是: jikerizhi 。因为众所周知的原因,有时图片加载不出来。 如果图片加载不出来可以直接通过搜索微信号来查找我的公众号。 |
334. Increasing Triplet Subsequence
这道题可以使用 300. Longest Increasing Subsequence 的思路来解决。具体思路分析可以看 最长上升子序列(动态规划 + 二分查找,清晰图解) - 最长上升子序列 - 力扣(LeetCode)。
更优的解题思路:
首先,新建两个变量 small 和 mid ,分别用来保存题目要我们求的长度为 3 的递增子序列的最小值和中间值。
接着,我们遍历数组,每遇到一个数字,我们将它和 small 和 mid 相比,若小于等于 small ,则替换 small;否则,若小于等于 mid,则替换 mid;否则,若大于 mid,则说明我们找到了长度为 3 的递增数组!
上面的求解过程中有个问题:当已经找到了长度为 2 的递增序列,这时又来了一个比 small 还小的数字,为什么可以直接替换 small 呢,这样 small 和 mid 在原数组中并不是按照索引递增的关系呀?
Trick 就在这里了!假如当前的 small 和 mid 为 [3, 5],这时又来了个 1。假如我们不将 small 替换为 1,那么,当下一个数字是 2,后面再接上一个 3 的时候,我们就没有办法发现这个 [1,2,3] 的递增数组了!也就是说,我们替换最小值,是为了后续能够更好地更新中间值!
另外,即使我们更新了 small ,这个 small 在 mid 后面,没有严格遵守递增顺序,但它隐含着的真相是,有一个比 small 大比 mid 小的前·最小值出现在 mid 之前。因此,当后续出现比 mid 大的值的时候,我们一样可以通过当前 small 和 mid 推断的确存在着长度为 3 的递增序列。 所以,这样的替换并不会干扰我们后续的计算!
参考资料
Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array.
Formally the function should:
<blockquote>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.</blockquote>
*Note: *Your algorithm should run in O(n) time complexity and O(1) space complexity.
Example 1:
Input: [1,2,3,4,5]
Output: true
Example 2:
Input: [5,4,3,2,1]
Output: false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* Runtime: 0 ms, faster than 100.00% of Java online submissions for Increasing Triplet Subsequence.
*
* Memory Usage: 39.3 MB, less than 93.02% of Java online submissions for Increasing Triplet Subsequence.
*/
public boolean increasingTriplet(int[] nums) {
if (Objects.isNull(nums) || nums.length < 3) {
return false;
}
int small = Integer.MAX_VALUE;
int mid = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; i++) {
int num = nums[i];
if (num <= small) {
small = num;
} else if (num <= mid) {
mid = num;
} else if (mid < num) {
return true;
}
}
return false;
}
/**
* Runtime: 152 ms, faster than 5.23% of Java online submissions for Increasing Triplet Subsequence.
*
* Memory Usage: 40.4 MB, less than 6.98% of Java online submissions for Increasing Triplet Subsequence.
*/
public boolean increasingTripletDp(int[] nums) {
if (Objects.isNull(nums) || nums.length < 3) {
return false;
}
int[] dp = new int[nums.length];
Arrays.fill(dp, 1);
int max = 1;
for (int i = 1; i < nums.length; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
max = Math.max(max, dp[i]);
if (max >= 3) {
return true;
}
}
return false;
}