334. 递增的三元子序列
题目: 给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。
进阶: 你能实现时间复杂度为 O(n) ,空间复杂度为 O(1) 的解决方案吗?
示例1:
输入:nums = [1,2,3,4,5]
输出:true
解释:任何 i < j < k 的三元组都满足题意
示例2:
输入:nums = [5,4,3,2,1]
输出:false
解释:不存在满足题意的三元组
示例3:
输入:nums = [2,1,5,0,4,6]
输出:true
解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6
解题思路:
利用本题只需要我们判定是否存在长度为 3 的上升子序列,而不需要回答 LIS 最大长度。
我们可以对 f 数组进行优化:使用有限变量进行替换(将 f 数组的长度压缩为 2),数组含义不变, f[1]]=x 代表长度为 1 的上升子序列最小结尾元素为 x,f[2]=y 代表长度为 2 的上升子序列的最小结尾元素为 y。从前往后扫描每个 nums[i],每次将 nums[i] 分别与 f[1] 和 f[2] 进行比较,如果能够满足 nums[i]>f[2],代表 nums[i] 能够接在长度为 2 的上升子序列的后面,直接返回 True,否则尝试使用 nums[i] 来更新 f[1] 和 f[2]。
这样,我们只使用了有限变量,每次处理 nums[i]nums[i] 只需要和有限变量进行比较,时间复杂度为 O(n),空间复杂度为 O(1)。
Java代码:
class Solution {
public boolean increasingTriplet(int[] nums) {
int n = nums.length;
long[] f = new long[3];
f[1] = f[2] = (int)1e19;
for (int i = 0; i < n; i++) {
int t = nums[i];
if (f[2] < t) return true;
else if (f[1] < t && t < f[2]) f[2] = t;
else if (f[1] > t) f[1] = t;
}
return false;
}
}
Go代码:
func increasingTriplet(nums []int) bool {
var f [3]int
f[1] = math.MaxInt32
f[2] = math.MaxInt32
for _, v := range nums {
if v > f[2] {
return true
} else if f[1] < v && v < f[2] {
f[2] = v
} else if f[1] > v {
f[1] = v
}
}
return false
}
复杂度分析:
- 时间复杂度:O(n)
- 空间复杂度:O(1)