思路:
序列表示是可以不连续的,依赖于前面的解,要使用动态规划(dp)
代码:
class Solution {
public int lengthOfLIS(int[] nums) {
if(nums.length==0) return 0;
int[] dp=new int[nums.length+1];
//把所有dp置为1,因为就算所有都不符合,到最后一个的时候自身也符合
Arrays.fill(dp,1);
int res=0;
for(int i=0;i<nums.length;i++){
for(int j=0;j<i;j++){
//此处的dp有不符合条件时"跳过"的功能
//注意j是每次从头遍历一遍,不只是i-1
//就算遍历到之前不符合条件的值也没事,dp就算+1,dp仍是前一个的值
//此处的if有跳过功能,若不满足,则dp[i]为1
if(nums[i]>nums[j]){
dp[i]=Math.max(dp[i],dp[j]+1);
}
}
//每次在第二重循环结束后都要比较一下
//因为不是dp[n-1]就是最大的,有可能dp[n-1]为1
res=Math.max(res,dp[i]);
}
return res;
}
}
分解:
1)设置双重循环,每一次i向前移动,都要从前往后遍历一次,由此满足了重叠子问题
for(int i=0;i<n;i++){
for(int j=0;j<i;j++)
2)设置if判断语句,有该j不满足就跳过的功能
if(nums[i]>nums[j])
3)以下是核心代码:
dp[i]有缓存的作用,当前dp[i]存储了之前的最长的序列,若满足nums[i]>nums[j]该条件,则比较dp[i]和dp[j]+1
比较dp[i]和dp[j]+1:
就算nums[i]>nums[j],如果dp[j]加上当前值之后仍小于之前存在的最长递增子序列的话,仍然取之前的那个(dp[i]缓存的)
同时也满足了动态规划的最优子问题
if(nums[i]>nums[j]){
dp[i]=Math.max(dp[i],dp[j]+1);
}
4)每次在第二重循环结束后都要比较一下,因为不是dp[n-1]就是最大的,有可能dp[n-1]为1(动态规划的细节坑)
res=Math.max(res,dp[i])
5)防止下标溢出,dp声明时,长度都在n的基础上加上1(n+1)
6)属于第二种dp形式:当前值依赖于前面所有计算好的值