一般常规 动态规划,一般都可以往 背包问题考虑,有明确的递推公式,但是对于很多问题,直接想,很难,所以得遵循数学的归纳法,由一般到特殊来求解。
数学归纳法
- 当证明 N =1 时结论,成立,并且 从0-N-1 的结论均成立,那么结合已知的信息,如何能推出 N 那么此结论成立
我们的定义是这样的:dp[i] 表示以 nums[i] 这个数结尾的最长递增子序列的长度。
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列
已经知道了 dp[0..4] 的所有结果,我们如何通过这些已知结果推出 dp[5] 呢
nums[0] 和 nums[4] 都是小于 nums[5] 的,然后对比 dp[0] 和 dp[4] 的值,我们让 nums[5] 和更长的递增子序列结合,得出 dp[5] = 3:
也就是说,实际上是 Math.max(1+1,2+1)
/**
* @param {number[]} nums
* @return {number}
*/
var lengthOfLIS = function(nums) {
let dp = new Array(nums.length +1).fill(1)
let max = 1
for(let i = 1;i<nums.length;i++){
for(let j = 0 ;j<i;j++){
if(nums[i] > nums[j]){
dp[i] = Math.max(dp[i],dp[j] + 1)
}
max = Math.max(max,dp[i])
}
}
return max
};
674. 最长连续递增序列
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。
思路
- 其实这个题目的和上提区别,在于连续,既然是连续,那就之关注相邻项是否为递增,又由于,结果项总只跟前一项有关,因此不需要双重循环,也就是不需要没次都 查询 0-i-1 之间的数值,只和 i-1 项有关
/**
* @param {number[]} nums
* @return {number}
*/
var findLengthOfLCIS = function(nums) {
let dp = new Array(nums.length).fill(1);
let max = 1
for(let i = 1;i<nums.length;i++){
if(nums[i] > nums[i-1]){
dp[i] = dp[i-1] +1
}
max = Math.max(max,dp[i])
}
return max
};
。