Medium

题目描述

给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。

如果存在这样的三元组下标 (i, j, k) 且满足 i < j < knums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false

示例 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
解释:有效的三元组是 (1, 4, 5),因为 nums[1] == 1 < nums[4] == 4 < nums[5] == 6。

提示:

  • 1 <= nums.length <= 5 * 10^5
  • -2^31 <= nums[i] <= 2^31 - 1

**进阶:**你能实现时间复杂度为 O(n) ,空间复杂度为 O(1) 的解决方案吗?

解题思路

解题思路

这道题要求找到一个长度为3的严格递增子序列。关键是理解题目只需要判断是否存在,而不需要找出具体的三元组。

方法一:贪心算法(推荐)

核心思想是维护两个变量:

  • first:遇到的最小值
  • second:在找到first之后遇到的最小值(且大于first

当我们遍历数组时:

  1. 如果当前数字小于等于first,更新first
  2. 如果当前数字大于first但小于等于second,更新second
  3. 如果当前数字大于second,说明找到了递增三元组

这个方法的巧妙之处在于,即使后续更新了first,之前的second仍然有效,因为它代表了"在某个更小值之后的第二小值"。

方法二:动态规划

可以用两个数组分别记录每个位置左边的最小值和右边的最大值,然后判断是否存在位置使得左最小值 < 当前值 < 右最大值。但这需要O(n)的额外空间。

贪心算法是最优解,时间复杂度O(n),空间复杂度O(1)。

代码实现

class Solution {
public:
    bool increasingTriplet(vector<int>& nums) {
        int first = INT_MAX, second = INT_MAX;
        
        for (int num : nums) {
            if (num <= first) {
                first = num;
            } else if (num <= second) {
                second = num;
            } else {
                return true;
            }
        }
        
        return false;
    }
};
class Solution:
    def increasingTriplet(self, nums: List[int]) -> bool:
        first = float('inf')
        second = float('inf')
        
        for num in nums:
            if num <= first:
                first = num
            elif num <= second:
                second = num
            else:
                return True
        
        return False
public class Solution {
    public bool IncreasingTriplet(int[] nums) {
        int first = int.MaxValue, second = int.MaxValue;
        
        foreach (int num in nums) {
            if (num <= first) {
                first = num;
            } else if (num <= second) {
                second = num;
            } else {
                return true;
            }
        }
        
        return false;
    }
}
var increasingTriplet = function(nums) {
    let first = Infinity, second = Infinity;
    
    for (let num of nums) {
        if (num <= first) {
            first = num;
        } else if (num <= second) {
            second = num;
        } else {
            return true;
        }
    }
    
    return false;
};

复杂度分析

复杂度类型复杂度说明
时间复杂度O(n)只需要遍历数组一次
空间复杂度O(1)只使用了常数个额外变量

相关题目