这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
输入:nums = [10,9,2,5,3,7,101,18] 输出:4 解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
我们一定要注意什么是子序列,这一点很重要,我再看到这道题的时候,我的第一想法是双指针,以前以后,使用滑动窗口,一次遍历解决,后来我发现,我根本解决不了,有一个关键问题,就是两个指针的变化都是动态的,单独的遍历没办法解决,想一想都是变化的,我们是不是就可以用动态规划去解决
如果使用动态规划,那最难的就是怎么去寻找我们的状态转移方程,怎么从这个状态转移到下一个状态
那题目说的找递增序列,我们可以通过寻找较大的数,不断增加,来转移我们的状态
每一个数都作为一个递增序列,与前面的数作比较如果有比自己小的记录一下我们序列长度,当然,当我们遇到比自身小的数字时,他可能也是一个小序列的结束,我们使小序列的长度加一
public int lengthOfLIS(int[] nums) {
if(nums.length==0){
return 0;
}
//记录以每个数结束的最长子序列子序列长度
int [] dp = new int[nums.length];
//自身长度就是1
dp[0] = 1;
int max = 1;
//第一次循环,
for(int i = 1;i<nums.length;i++){、
//设置初始大小
dp[i] = 1;
//从第一个数开始比较
for(int j=0; j<i;j++){
//如果小,增加序列长度
if(nums[j]<nums[i]){
//增加序列长度,并比较此次循环最长序列
dp[i]=Math.max(dp[i],dp[j]+1);
}
}
//保存最长子序列
max=Math.max(max,dp[i]);
}
return max;
}
动态规划的题,主要就是两点,
第一,你能意识到他是动态规划的题
第二,发现状态转移方程
这两点,在我看来,都是比较难想的两件事,如果能把这两个想明白,就很容易把题解出来,想不出,那就完了,这个可能就是为什么动态规划难的原因。