动态规划专题:子序列问题的核心思路与实战
前言:从 O(N) 到 O(N²)
和子数组不同,子序列允许跳跃选择。核心在于状态定义:dp[i] 通常表示以 i 位置结尾的最长子序列长度。由于不连续,i 可以接在 0 到 i-1 之间任何一个符合条件的 j 后面,这通常意味着需要双层循环。如果单个数无法确定规律(如等差、斐波那契),则需定义两个数(dp[i][j] 表示以 i 和 j 结尾)。
一、最长递增子序列 (Medium)
题目:300. 最长递增子序列
找到最长严格递增子序列的长度。
输入:[10,9,2,5,3,7,101,18]
输出:4 ([2,3,7,101])
思路:
状态 dp[i] 表示以 nums[i] 结尾的最长递增子序列长度。
遍历 i 时,往回看所有 j < i。若 nums[j] < nums[i],说明能接在 j 后面,取最大值更新:dp[i] = max(dp[j] + 1)。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n, 1);
int ret = 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);
}
}
ret = max(ret, dp[i]);
}
return ret;
}
};
(注:此题存在 O(NlogN) 贪心解法,但此处重点讲解 DP 模型)


