300. 最长递增子序列(中等)twice

1,问题描述

300. 最长递增子序列

难度:中等

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:

1
2
3
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

示例 2:

1
2
输入:nums = [0,1,0,3,2,3]
输出:4

示例 3:

1
2
输入:nums = [7,7,7,7,7,7,7]
输出:1

提示:

  • 1 <= nums.length <= 2500
  • -104 <= nums[i] <= 104

进阶:

  • 你能将算法的时间复杂度降低到 O(n log(n)) 吗?

2,初步思考

​ 最开始以为使用单调栈来求解,但是我的想法有误

​ 看完题解发现是动态规划和贪心

3,代码处理

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import java.util.*;

public class _300最长递增子序列 {

// 动态规划
// 时间复杂度:O(n^2)
// 空间复杂度:O(n)
// 状态转移方程:dp[i] = max(dp[j]) + 1, j < i && nums[j] < nums[i]
public int lengthOfLIS_dp(int[] nums) {
int len = nums.length;
int[] dp = new int[len];
dp[0] = 1;
for (int i = 1; i < len; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
dp[i] = Math.max(dp[i], dp[j]);
}
}
dp[i] += 1;
}
return Arrays.stream(dp).max().getAsInt();
}

// 二分查找
// 维护特定长度的最小值数据
public int lengthOfLIS_binary_search(int[] nums) {
List<Integer> list = new ArrayList<>();
list.add(nums[0]);
for (int i = 1; i < nums.length; i++) {
if (list.getLast() < nums[i]) {
list.add(nums[i]);
} else {
int idx = Collections.binarySearch(list, nums[i]);
if (idx < 0) {
idx = -idx - 1;
}
list.set(idx, nums[i]);
}
}
return list.size();
}

// 单调栈(monostone stack)错误题解
public int lengthOfLIS(int[] nums) {
int max = 0;
Deque<Integer> stack = new ArrayDeque<>();
for (int num : nums) {
if (stack.isEmpty()) {
stack.addLast(num);
} else {
while (!stack.isEmpty() && stack.peekLast() >= num) {
stack.pollLast();
}
stack.add(num);
}
max = Math.max(max, stack.size());
}
return max;
}

public static void main(String[] args) {
_300最长递增子序列 longestIncreasingSubsequence = new _300最长递增子序列();
// System.out.println(longestIncreasingSubsequence.lengthOfLIS_dp(new int[]{10, 9, 2, 5, 3, 7, 101, 18}));
// System.out.println(longestIncreasingSubsequence.lengthOfLIS_dp(new int[]{4, 10, 4, 3, 8, 9}));
System.out.println(longestIncreasingSubsequence.lengthOfLIS_dp(new int[]{1, 3, 6, 7, 9, 4, 10, 5, 6}));
}
}