300.最长递增子序列(中等)

思路:

序列表示是可以不连续的,依赖于前面的解,要使用动态规划(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形式:当前值依赖于前面所有计算好的值

猜你喜欢

转载自blog.csdn.net/di_ko/article/details/115228290
今日推荐