300. 最长递增子序列
题目链接:300. 最长递增子序列
方法:动态规划
解题思路
- 状态表示:\(dp[]\)
- 集合:表示以 \(i\) 结尾的所有递增子序列;
- 属性:\(dp[i]\) 表示集合中最长子序列的长度。
- 状态计算:
- 集合划分:枚举以 \(i\) 结尾的所有递增子序列的其前一个元素可能的下标 [0, i - 1],将其划分为以 \(i\) 结尾的所有递增子序列中前一个元素是 \(j\)的集合,\(0 <= j <= i - 1, nums[j] < nums[i]\)。
- \(dp[i] = max\{dp[j] + 1, 1\}\)
代码
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
int dp[n]; memset(dp, 0, sizeof(dp));
dp[0] = 1;
int ans = 1;
for (int i = 1; i < n; i ++ ) {
dp[i] = 1;
for (int j = 0; j < i; j ++ ) {
if (nums[i] > nums[j]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
ans = max(ans, dp[i]);
}
return ans;
}
};
优化解法:单调 + 二分
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
int ans = 0, q[n + 1]; memset(q, 0, sizeof(q));
q[0] = -2e9;
for (int i = 0; i < n; i ++ ) {
int l = 0, r = ans;
while (l < r) {
int mid = l + r + 1 >> 1;
if (q[mid] < nums[i]) l = mid;
else r = mid - 1;
}
ans = max(ans, r + 1);
q[r + 1] = nums[i];
}
return ans;
}
};
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
int ans = 0, q[n + 1]; memset(q, 0, sizeof(q));
q[0] = -2e9;
for (int i = 0; i < n; i ++ ) {
int idx = lower_bound(q, q + ans + 1, nums[i]) - q;
ans = max(ans, idx);
q[idx] = nums[i];
}
return ans;
}
};
复杂度分析
时间复杂度:\(dp\)—\(O(n^2)\),优化—\(O(nlogn)\);
空间复杂度:\(O(n)\)。

浙公网安备 33010602011771号