这道题之前刷代码随想录的时候也刷过,现在又给忘完了。自己尝试着写了一下,发现怎么写都写不对,直接去看视频了。。我自己写的时候的定义是:考虑下标0 ~ i
范围内索赔能取到的最长严格递增子序列的长度,后面发现在写递推公式的时候怎么都写不对,这道题的dp
数组的含义为:以nums[i]
为结尾的情况下,其最长严格递增子序列的长度。那么递推公式就很好想了,在以nums[i]
为结尾的情况下,我们从头开始搜索,如果遇到nums[j] < nums[i]
的情况,则说明nums[i]
可以作为以nums[j]
结尾的子序列的下一个元素,我们需要对比dp[j] + 1
与dp[i]
之间的大小关系,取较大值作为新的dp[i]
。遍历顺序也很好想,二重循环都是从小到大遍历的。下面写下递归五部曲:
1.确定dp[i]的含义:以nums[i]为结尾的情况下,其最长严格递增子序列的长度
2.确定递推公式 dp[i] = max(dp[j] + 1, dp[i]) (只有nums[i] > nums[j]才会触发)
3.dp数组初始化 dp[0] = 1
4.确定遍历顺序:从左往右遍历
5.打印数组(省略)
值得注意的是,我们最终要返回的不一定是dp[s.size() - 1]
,因为最后一个元素不一定是最大元素,最大元素可能在前面的任意位置,例如数组[0, 1, 2, 3, 4, 5, 1]
,最大长度在元素5
这里产生,我们需要用一个额外变量result
来维护最大长度。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
//1.确定dp[i]的含义:以nums[i]为结尾的情况下,其最长严格递增子序列的长度
//2.确定递推公式 dp[i] = max(dp[j] + 1, dp[i]) (只有nums[i] > nums[j]才会触发)
//3.dp数组初始化 dp[0] = 1
//4.确定遍历顺序:从左往右遍历
//5.打印数组(省略)
int n = nums.size();
vector<int> dp(n, 1);
int result = 1; //用于记录整个数组中的最长子序列的长度
//初始化
dp[0] = 1;
for(int i = 1; i < n; i++){ //逐渐扩大数组范围
for(int j = 0; j < i; j++){ //内循环则确定nums[i]为结尾的情况下所能取到的最长严格递增子序列的长度
if(nums[i] > nums[j]) //nums[i]可以作为以nums[j]结尾的子序列的下一个元素时
dp[i] = max(dp[j] + 1, dp[i]);
}
result = max(result, dp[i]); //维护最长严格递增子序列的长度
}
return result;
}
};