最长递增子序列
约 428 字大约 1 分钟
2025-02-26
最长递增子序列
给你一个整数数组nums
,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4
考虑以i为结尾的最长递增子序列长度。从i向前来枚举,找到比i小的元素j,那么dp[i] = dp[j] + 1。
class Solution {
public:
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]; // 注意这里是引用
if (res > 0) { // 之前计算过
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;
}
};
上面代码自然而然可以用动态规划来进行优化。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
if (n == 1) {
return 1;
}
int res = INT_MIN;
vector<int> dp(n, 1);
for (int i = 1; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
res = max(res, dp[i]);
}
return res;
}
};
那么最佳的方案nlogn复杂度的方案有些复杂,详情可看视频
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> g;
for (int x : nums) {
auto it = ranges::lower_bound(g, x);
if (it == g.end()) {
g.push_back(x); // >=x 的 g[j] 不存在
} else {
*it = x;
}
}
return g.size();
}
};
更新日志
2025/3/2 09:12
查看所有更新日志
041c6
-update tencent interview于