代码随想录笔记_动态规划
代码随想录二刷笔记记录
LC674.最长连续递增序列
题目
子序列问题
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], …, nums[r - 1], nums[r]] 就是连续递增子序列。
示例 1:
输入:nums = [1,3,5,4,7]
输出:3
解释:最长连续递增序列是 [1,3,5], 长度为3。 尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。
示例 2:
输入:nums = [2,2,2,2,2]
输出:1
解释:最长连续递增序列是 [2], 长度为1。
提示:
- 0 <= nums.length <= 10^4
- -10^9 <= nums[i] <= 10^9
思路分析
思路:
思路:递增子序列 -> 子序列问题 -> 动态规划
既然是递增子序列,容易想到两两相比较的方法。第 i 个元素和第 i - 1 个元素比较,若 nums[i] > nums[i-1] 则 dp[i] + 1 ,否则 dp[i] 保持为1
动态规划五部曲
1.确定dp数组及其下标的含义
dp[i] : 表示以 i 为结尾的连续递增子序列长度为 dp[i]
2.确定递推公式
根据思路分析可知,需遍历数组,同时比较 当前元素 及其 前一个元素的大小。
回顾 LC300, 需要比较的是当前元素,和其之前的所有元素大小。这是这两题的区别。
if(nums[i+1] > nums[i]){
dp[i+1] = dp[i]+1;
}
//表示以 i+1 结尾的子序列Len(i+1)长度比
//以 i 结尾的子序列Len(i)长度大
3.初始化
如果数组不为空,则子序列至少为 1。即使数组为 [2,2,2,2,2] ,子序列长度也至少为1
dp[i] 初始化为1
4.遍历顺序
根据递推公式可知,从前往后遍历
//注意,由于比较的是 nums[i] 和 nums[i-1] ,因此这里从 1 开始遍历
for(int i = 1;i < nums.length;i++){
if(nums[i] > nums[i-1]){
dp[i] = dp[i-1] + 1;
}
}
5.推演分析
以示例1 [1,3,5,4,7] 为例
0 | 1 | 2 | 3 | 4 | |
---|---|---|---|---|---|
初始化 | 1 | 1 | 1 | 1 | 1 |
第1次循环 | 1 | 2 | 1 | 1 | 1 |
第2次循环 | 1 | 2 | 3 | 1 | 1 |
第3次循环 | 1 | 2 | 3 | 1 | 1 |
第4次循环 | 1 | 2 | 3 | 1 | 2 |
代码实现
完整代码实现
public int findLengthOfLCIS(int[] nums) {
int len = nums.length;
//初始化
if (0 == len) return 0;
int[] dp = new int[len];
Arrays.fill(dp,1);
//遍历
for (int i = 1; i < len; i++) {
if (nums[i] > nums[i-1])
dp[i] = dp[i-1] + 1;
}
int res = Arrays.stream(dp).max().getAsInt();
return res;
}