334. Increasing Triplet Subsequence(递增的三元子序列)

334. Increasing Triplet Subsequence(递增的三元子序列)

1. 题目描述

给你一个整数数组 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 <= 5 * 105
  • -231 <= nums[i] <= 231 - 1

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

题目连接:中文题目英文题目

2.思路解析

简单的暴力解应该大家应该都能想到,只要三层循环,去查找有没有符合题意的三元组即可,但是这样的事件复杂非常的不可接受。又没有更加高效的方法呢?而且Follow ups里面提示了可以在O(n)时间之内解决,那么问题的突破口在哪里呢?

大家需要注意这题的目标仅是报告有没有满足条件的三元组,而并非要求实际去报告这个三元组是什么。 但是因为先入为主的思维,我们会掉入这个一个陷进:

要去寻找一定满足题目限定条件的三元组,即 i < j < k ,使得 nums[i] < nums[j] < nums[k]

虽然这样思路是对的,但是确无法高效解题。这是为什么呢?现在先放宽查找条件,假设在下标k处,我们需要寻找一个三元组满足下列条件:

nums[i] < nums[j] < nums[k],且max(i,j) < k

如果原题目的要求是简化后的,那么解题思路也非常简单了,我们并不关心i和j的顺序,只需要从左往右依次扫描(假设下标升序),只要能找到两个不相同的最小值和次小值,并且它们后边还有一个都大于它们的数,就能找到满足要求的三元组。并且最小值和次小值具体有多小,我们是不用关心,只要它们能满足nums[i] < nums[j]即可,所以我们可以扫描的同时,不断更新最小值和次小值。

那么这样处理以后,我们就得到了满足下面条件的三元组:

nums[i] < nums[j] < nums[k],且max(i,j) < k

但原题意需要限定i < j,但上面的条件明显有两种情况:1) i < j;2) i > j。如果是1),获得的三元组一定满足原题目要求,但如果是2)呢?很显然还需要有一个额外条件才能满足题意:

当i > j时形成的三元组满足题意,当且仅当存在下标m < j,且nums[m] < nums[ i ],那么可得m < j < k, nums[m] < nums[j] < nums[k],这样的三元组(m,j,k)也能满足题意

所以只要我们在之前的算法上面保证最小值一定被至少更新一次,就能保证最后一定存在一个下标m,使得得到的三元组满足题意。而且上面的分析过程也是本题的证明过程,即这样扫描为什么一定能找到题目要求的三元组。

通过上面的讲解,相比大家也能理解讨论里面给到的线性时间算法的思路,这个算法比较难理解的就是会出现i > j,但最后依然能找到满足题意的三元组。比如输入案例:[1,0,2,0,-1,3],最后最小值为-1,次小值为2,最大值为3,但(-1,2,3)并不满足题意,因为-1和2的下标不满足,但在更新最小值为-1之前,我们找到了一个比-1大的最小值0,从而找到了下标m,也能找到满足的题意得三元组。因此这个思路只能报告有没有这样得三元组,但不能正确得给到这个三元组具体是什么。

3.代码

个人算法项目:Algorithm

public boolean increasingTriplet( int[] nums ) {
    int s = Integer.MAX_VALUE, b = Integer.MAX_VALUE;
    for ( int n : nums ) {
        // found a number less than the smallest.
        if ( n <= s ) s = n;
        // found a number less than the second smallest,
        // but greater than the smallest.
        else if ( n <= b ) b = n;
        // found a number greater than both numbers.
        // i.e. found the target triplet.
        else return true;
    }

    // no such a triple.
    return false;
}

4. 参考资料

5. 免责声明

※ 本文之中如有错误和不准确的地方,欢迎大家指正哒~
※ 此项目仅用于学习交流,请不要用于任何形式的商用用途,谢谢呢;


Pixiv Artist ID:98903239

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值