题目描述
给你一个整数数组 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] <= - 1
解题
题解①:贪心
根据题意我们要找到满足这些条件的情况: i < j < k
,使得 nums[i] < nums[j] < nums[k]
那我们不妨将这题换一种问法,将nums[i]和nums[j]看成一组,在这一组中,确保i < j并且nums[i]<nums[j]即可,现在我们需要找出一个数nums[k]大于这个组也就是大于nums[j],同时还要保证k > j。这么一说,咋一看感觉跟原题目并没区别,为什么要单独将前两个数划为一组呢?不急,我们接着往下看。
拿上面的实例3举例:将实例3的数组[2,1,5,0,4,6]用图表示出来:
也容易得知,其中三元组(3,4,5)、(0,1,4)...等等都是满足题意 i<j<k且nums[i]<nums[j]<nums[k]的,
为了方便观看我们用不同颜色的线标出来
三元组为(3,4,5)的情况: 三元组为(0,1,4)的情况:
画这个图是为了更直观地发现我们该如何解决这个问题,到这里我们应该就有很清晰的解题思路了:
①确保绿线也就是nums[k]必须在橙线nums[j]上方,也就是nums[k]>nums[j],只要找到符合这个条件的绿线,也就是找到一种nums[k] > nums[j]的情况,那么答案也就出来了。
②那我们怎样才能更大概率或者说更好地找到这种组合呢?那肯定是让橙线越低越好,也就是nums[j]越小越好。因为nums[j]越小,满足j < k且nums[j] < nums[k]条件的k才越多。
③那橙线能无限低也就是nums[j]能无限小吗?肯定是不能的,约束nums[j]的就是nums[i]。
所以,我们要做的是,定义两个数,a和b(对应着红线和橙线),遍历数组:for(int i = 0;i < nums.length;++i)。确保a永远是nums[0] ~ nums[i]中最小的值,确保b永远是在 ( a,nums[i] ]区间内最小的一个。当遍历到 nums[i] > nums[j]即可以返回true,遍历完还没找到就返回false。
不难得出下面代码:
public boolean increasingTriplet(int[] nums) {
if (nums.length < 3)
return false;
int a = nums[0];
int b = Integer.MAX_VALUE;
for (int i = 1;i < nums.length;++i){
int num = nums[i];
if (num > b){
return true;
} else if (num > a){
b = num;
} else {
a = num;
}
}
return false;
}
所以,这种解法我们可以发现,它贪心是贪在nums[i]和nums[j]尽量小这方面。