算法初探LeetCode-递增的三元子序列

158 阅读2分钟

LeetCode334-递增的三元子序列

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

如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[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
解释: 三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6

提示:

  • 1<=nums.length<=51051 <= nums.length <= 5 * 10^5
  • 231<=nums[i]<=2311-2^{31} <= nums[i] <= 2^{31} - 1

思路分析

整体思路仍然是遍历nums数组,找到是否存在可能。由于无需找到所有满足条件的序列,所以可以用first和second代表前两个数,不断更新first和second,找到是否存在满足条件

第一种方法采用双指针的思想,针对这个题的三元子序列,如果是四元或更高元则不通用。主要思路是维护当前访问数组的最小值和最小值右侧大于最小值的最小的一个。具体步骤顺序遍历数组,首先确定当前已访问的数组的最小值,即如果小于等于min值的话更新min值,如果大于min,判断是否小于等于max值,如果是,更新max值。如果大于max值,则说明有三元子序列。nums[i]一定可以接在长度为j的递增子序列后面,形成一个长度为j+1的递增子序列

第二种方法动态规划,主要思路是维护和更新以i为结尾的三元子序列的最长递增长度。转移方程为dp[i] = max{dp[i], dp[j] + 1} (0<=j<i),已有长度为j+1的递增子序列,但nums[i]把其尾部的最小值降低了,为后续增长提供了可能性

算法代码

class Solution {
    public boolean increasingTriplet(int[] nums) {
        if (nums == null || nums.length == 0) {
            return false;
        }
        int min = Integer.MAX_VALUE, max = Integer.MAX_VALUE;
        for (int num: nums) {
            if (num <= min) {
                min = num;
            } else if (num <= max) {
                max = num;
            } else {
                return true;
            }
        }
        return false;
    }
}

结果详情

Snipaste_2023-05-09_22-00-26.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!