一起刷力扣之【334. 递增的三元子序列】

137 阅读1分钟

这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战

题目

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

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

示例

输入: nums = [1,2,3,4,5]
输出: true
解释: 任何 i < j < k 的三元组都满足题意
输入: nums = [5,4,3,2,1]
输出: false
解释: 不存在满足题意的三元组
输入:nums = [2,1,5,0,4,6]
输出:true
解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6

提示

  • 1 <= nums.length <= 5 * 105^5
  • -231^{31} <= nums[i] <= 231^{31} - 1

解题思路

三层循环

遇到需要多个元素进行比较的题,可能最容易想到的就是多层循环,简单粗暴,上来几个for循环下去就搞定了。

class Solution {
    public boolean increasingTriplet(int[] nums) {
        int n = nums.length;

        for(int i = 0; i < n - 2; ++i){
            for(int j = i + 1; j < n - 1; ++j){
                for(int k = j + 1; k < n; ++k){
                    if(nums[i] < nums[j] && nums[j] < nums[k]){
                        return true;
                    }
                }
            }
        }

        return false;
    }
}

image.png

一遍遍历

多层遍历虽然是最容易实现的,但是其时间复杂度也是最高的,从上面的结果我们可以看到,直接就超出时间限制了,必须对其进行优化才行。

在这里可以先将前面两个元素定义出来,用类似取最大值的方式,来判断是否符合条件。

  • 第一个元素f,取值首位元素
  • 第二个元素s,先设置成最大值,然后遍历后续元素,将其更新为最接近f的次小值
class Solution {
    public boolean increasingTriplet(int[] nums) {
        int n = nums.length;
        if(n < 3){
            return false;
        }

        int f = nums[0], s = Integer.MAX_VALUE;
        for(int i = 1; i < n; ++i){
            if(nums[i] > s){
                // 由于s必定大于f,如果当前元素大于s表示条件成立,直接返回结果
                return true;
            }else if(nums[i] > f){
                // 当前元素小于s且大于f,更新s的值,使其变得更小更接近f
                s = nums[i];
            }else{
                // 以上条件都不满足,更新f为最小值
                f = nums[i];
            }
        }

        return false;
    }
}