LIS 模型及其衍生
前言
和子数组(必须连续)不同,子序列可以跳着选。状态定义通常以 dp[i] 表示以 i 位置结尾的最长子序列长度。由于不连续性,i 可以接在 0 到 i-1 任何一个符合条件的 j 后面,因此通常需要双层循环。如果遇到等差、斐波那契等规律,可能需要定两个数,即 dp[i][j] 表示以 i 和 j 结尾。
最长递增子序列
题目描述
找到最长严格递增子序列的长度。
输入:[10,9,2,5,3,7,101,18]
输出:4 ([2,3,7,101])
核心思路
- 状态:
dp[i]表示以nums[i]结尾的最长递增子序列长度。 - 转移:站在
i位置,往回看所有j(0 <= j < i)。如果nums[j] < nums[i],说明能接在j后面。选一个最长的dp[j]接上去。dp[i] = max(dp[j] + 1)。
代码实现
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n = nums.size();
// 初始化为 1,因为每个元素自己就是一个长度为 1 的子序列
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 = (ret, dp[i]);
}
ret;
}
};


