8、递增的三元子序列

原题力扣《递增的三元子序列》
难度中等

题目

给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。
如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。

示例 1:

1
2
3
输入:nums = [1,2,3,4,5]
输出:true
解释:任何 i < j < k 的三元组都满足题意

示例 2:

1
2
3
输入:nums = [5,4,3,2,1]
输出:false
解释:不存在满足题意的三元组

示例 3:

1
2
3
4
输入: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) 的解决方案吗?

解题

个人

关键:硬解的

  1. 条件:i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true
  2. 嵌套循环,先找 i
  3. 再循环找 j,j 找到后再循环找 k
  4. 三层嵌套循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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

  1. 若 third > second,则找到了,返回 true
  2. 若 third < second 但 third > first,则 second = third,继续循环找 third
  3. 若 third < first,则 first = third,继续循环找 third(虽然 first 在 second 之后了,但在 second 之前,存在过老的 first 并小于 second)

举例:[3, 2, 4, 1, 7, 6, 9]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
};

总结

上一道题目才做双循环的,就给忘了,让后又变成硬解了。
以后遇到数组的,先考虑双指针、再考虑能否生成两个数组,最后再硬解


8、递增的三元子序列
https://mrhzq.github.io/职业上一二事/算法学习/每日算法/8、递增的三元子序列/
作者
黄智强
发布于
2024年1月13日
许可协议