Longest Increasing Subsequence
franklinqin0 DPGreedyBinary Search
# Solution
Let be the length of the array.
The brute force solution is omitted.
# Follow Up
Could you come up with the solution?
# DFS Recursion w/ Memo
表示以 nums[i] 结尾的最长递增子序列(LIS)的长度。
def lengthOfLIS(self, nums: List[int]) -> int:
# dfs(i): 以 nums[i] 结尾的LIS
@cache
def dfs(i):
res = 0
for j in range(i):
if nums[j] < nums[i]:
res = max(res, dfs(j))
return res + 1 # 1 means num[i]
n = len(nums)
return max(dfs(i) for i in range(n))
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
vector<int> memo(n);
auto dfs = [&](this auto&& dfs, int i) -> int {
int& res = memo[i]; // reference here
if (res > 0) { // having calculated
return res;
}
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
res = max(res, dfs(j));
}
}
return ++res;
};
int ans = 0;
for (int i = 0; i < n; i++) {
ans = max(ans, dfs(i));
}
return ans;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# DP
Complexity
time:
space:
def lengthOfLIS(self, nums: List[int]) -> int:
# 以 nums[i] 结尾的LIS
n = len(nums)
dp = [0 for _ in range(n)]
for i in range(n):
for j in range(i):
if nums[j] < nums[i]:
dp[i] = max(dp[i], dp[j])
dp[i] += 1
return max(dp)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Could you improve it to time complexity?
# Greedy Algorithm & Binary Search
g[i] 表示长为 i+1 的上升子序列的末尾元素的最小值。
Complexity
time:
space:
def lengthOfLIS(self, nums: List[int]) -> int:
g = []
for x in nums:
j = bisect_left(g, x)
if j == len(g):
g.append(x)
else:
g[j] = x
return len(g)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9