涉及题目
最长连续递增序列
最长递增子序列
最长重复子数组
动态规划五部曲
确定 dp 数组及其下标的含义
状态转移方程
初始化
遍历顺序
手动模拟
最长连续递增序列
3.1 思路
第一步:
dp[i] 表示:以数组中第 i 个元素(nums[i])结尾的最长连续递增子序列的长度。 为什么要定义'以 nums[i] 结尾'?因为连续递增的特性要求子序列必须是连续的,nums[i] 能否接在 nums[i-1] 后面,只需要比较两者的大小,而'以 i 结尾'的定义能让我们通过前一个位置的结果推导出当前位置的结果。
第二步:
核心逻辑:如果当前元素 nums[i] 大于前一个元素 nums[i-1],说明可以把 nums[i] 接在以 nums[i-1] 结尾的递增子序列后面,此时 dp[i] = dp[i-1] + 1; 如果 nums[i] <= nums[i-1],说明无法形成连续递增,以 nums[i] 结尾的最长连续递增子序列只能是它自己,因此 dp[i] 保持初始化的 1 即可。
第三步:
每个元素自身可以构成一个长度为 1 的递增子序列,因此需要将 dp 数组的所有元素初始化为 1(Arrays.fill(dp, 1)); 同时初始化结果变量 res = 1,因为数组至少有一个元素,最长长度不会小于 1。
第四步:
因为 dp[i] 的值依赖于 dp[i-1],所以需要从左到右遍历数组(i 从 1 开始,到 len-1 结束); 遍历过程中,每计算出一个 dp[i],就和 res 比较,更新 res 为当前最大值。
第五步:
以示例数组 nums = [1,3,5,4,7] 为例: 初始化:dp = [1,1,1,1,1],res = 1; i=1(nums[1]=3 > nums[0]=1):dp[1] = 1+1=2,res 更新为 2; i=2(nums[2]=5 > nums[1]=3):dp[2] = 2+1=3,res 更新为 3; i=3(nums[3]=4 < nums[2]=5):dp[3] 保持 1,res 仍为 3; i=4(nums[4]=7 > nums[3]=4):dp[4] = 1+1=2,res 还是 3; 最终返回 res=3,对应最长连续递增子序列 [1,3,5]。
3.2 实现代码
import java.util.Arrays;
class Solution {
public int findLengthOfLCIS(int[] nums) {
// 1. 处理边界情况:如果数组为空,直接返回 0
if (nums == null || nums.length == 0) {
return 0;
}
// 获取数组长度
int len = nums.length;
// 2. dp 数组定义:dp[i] 表示以 nums[i] 结尾的最长连续递增子序列的长度
int[] dp = new int[len];
// 3. 初始化:每个元素自身是长度为 1 的子序列,所以全部填充为 1
Arrays.fill(dp, );
;
( ; i < len; i++) {
(nums[i] > nums[i - ]) {
dp[i] = dp[i - ] + ;
}
(dp[i] > res) {
res = dp[i];
}
}
res;
}
}

