leetcode刷题系列(动态规划) 二.最大递增子序列

文章目录

题目

给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

思路

我们假设dp[i]为长度为i的上升子序列尾元素的值,
我们再设置一个标志位max记录当前最长的子序列的长度

接下就是遍历整个数组data
当我们当前遍历的元素的值data[i]与dp[max]相比较时
data[i] > dp[max]时:
那直接可以将最大上升子序列扩大规模了,

例如: 子序列为 1 3 5
当前元素为7 ,
7 > 5所以子序列直接新增一个
最大子序列更新为 1 3 5 7

data[i] = dp[max]时
不满足上升子序列的要求直接continue,开始下一次循环
data[i] < dp[max]时
我们所有的推论的基础都在于
dp[i]为长度为i的上升子序列尾元素的最优值
现在我们需要去维护这个理论基础
去遍历整个dp数组,然后找到第一个小于data[i]的值然后更新该值,这样才能保证整个dp数组为最优解

例如当前dp数组 1 3 5 6 7
当前元素为4
为什么要只更新第一个小于data[i] 的值:,也就是dp数组中的5
1.当我们更新data[i - 1]的值的时候
那也就是我们将3 的值更新为当前元素 4
这样反而将元素的值提高了,对于递增子序列来说,你尾部元素的值越高,新元素越难添加到尾部,也就是"竞争力"下降了
2.当我们更新data[i + 1]的值的时候
那也就是我们将6的值更新为当前元素 4
dp数组就变成了 1 3 5 4 7
这样就违背递增序列的特性了,因为排在后面的元素反而比前面的元素小了
3.为什么要更新data[i]的值
因为在递增数组子序列中,我们应该将尾部元素尽可能的变小,从而方便新元素加入到尾部,使子序列变长,也就是提升"竞争力"

动态规划的状态方程很容易得出
dp[++max] = data[i] (data[i] > dp[max])
dp[j] = data[i] ( data[i] < dp[max] dp[j]为dp数组第一个小于data[i] 的值)

代码

class Solution {
    public int lengthOfLIS(int[] nums) {
        if(nums.length <= 1){
            return nums.length;
        }
        //最大长度
        int max = 1;
        //dp[i]表示第i长的子序列,最后的元素
        int[] dp = new int[nums.length + 1];
        dp[1] = nums[0];
        for(int i = 1;i < nums.length;i++){
            //如果当前元素比最大的那个子串的最后一个元素还要大
            //那就直接长度加一,新子串的最后一个元素为当前元素
            if(nums[i] > dp[max]){
                dp[++max] = nums[i];
            }else if(nums[i] < dp[max]){
                //如果当前元素比最大的那个子串的最后一个元素要小
                //那就要更新dp数组,保证每一个子串都是最优解
                for(int j = 1 ;j <= max; j++){
                    //因为是递增,所以是<=,在将等于的时候直接终止循环
                    if(nums[i] <= dp[j]){
                        dp[j] = nums[i]; 
                        break;
                    }
                }
            }
        }
        return max;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值