原题:力扣《递增的三元子序列》
难度:中等
题目:
给你一个整数数组 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 * 10^5
- -231 <= nums[i] <= 231 - 1
进阶:你能实现时间复杂度为 O(n) ,空间复杂度为 O(1) 的解决方案吗?
解题:
个人:
关键:硬解的
- 条件:i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true
- 嵌套循环,先找 i
- 再循环找 j,j 找到后再循环找 k
- 三层嵌套循环
var increasingTriplet = function (nums) {
let i = 0;
let = j = k = 0;
const len = nums.length;
for (; i < len; i++) {
for (let index = i + 1; index < len; index++) {
if (nums[index] > nums[i]) {
j = index;
for (let index = j + 1; index < len; index++) {
if (nums[index] > nums[j]) {
k = index;
break;
}
}
if (k) {
break;
}
}
}
if (j === 0) {
continue;
}
if (j > 0 && k > 0) {
break;
}
}
return Boolean(j > 0 && k > 0);
};
Case 通过,但提交后超长数据运行报错
耗时:40 min
官方:
关键1:双循环
思路1:1<= i <= len - 1,存在 n[左侧最小] < n[i] < n[右侧最大]
将数据分为两块,LMin 存放下标 i 时,左侧最小的、RMax 存放下标 i 时,右侧最大的
最后判断是否满足 LMin[i] < n[i] < RMax[i]
var increasingTriplet = function (nums) {
const len = nums.length;
const LMin = [];
const RMax = [];
LMin[0] = nums[0];
for (let index = 1; index < nums.length; index++) {
const element = nums[index];
LMin[index] = Math.min(LMin[index - 1], element);
}
RMax[len - 1] = nums[len - 1];
for (let index = len - 2; index >= 0; index--) {
const element = nums[index];
RMax[index] = Math.max(RMax[index + 1], element);
}
for (let index = 0; index < nums.length; index++) {
const element = nums[index];
if (element > LMin[index] && element < RMax[index]) {
return true;
}
}
return false;
};
关键2:贪心
思路2:初始设置 first = nums[0];second = 无穷大;现在循环找 third
- 若 third > second,则找到了,返回 true
- 若 third < second 但 third > first,则 second = third,继续循环找 third
- 若 third < first,则 first = third,继续循环找 third(虽然 first 在 second 之后了,但在 second 之前,存在过老的 first 并小于 second)
举例:[3, 2, 4, 1, 7, 6, 9]
第 1 次时:
first = nums[0] = 3; second = Number.MAX_VALUE; third = nums[1] = 2
判断 third,满足 third < first,则 first = third = 2
第 2 次时:
first = 2; second = Number.MAX_VALUE; third = nums[2] = 4
判断 third,满足 second > third > first,则 second = third = 4
第 3 次时:
first = 2; second = 4; third = nums[3] = 1
判断 third,满足 third < first,则 first = third = 1
第 4 次时:
first = 1; second = 4; third = nums[4] = 7
判断 third,满足 third > second,则找到了,终止循环,并返回 true
此时找到的三元下标为:x,2,4,对应值为 num[x],4,7
其中的 x 为下标 2 之前的任意一个,即老 first 用过的下标 0,1
0,2,4 对应值为 3,4,7
1,2,4 对应值为 2,4,7
var increasingTriplet = function (nums) {
let first = nums[0];
let second = Number.MAX_VALUE;
for (let index = 0; index < nums.length; index++) {
const third = nums[index];
if (third > second) return true;
else if (third > first) second = third;
else first = third;
}
return false;
};
总结:
上一道题目才做双循环的,就给忘了,让后又变成硬解了。
以后遇到数组的,先考虑双指针、再考虑能否生成两个数组,最后再硬解