最长递增子序列

https://leetcode-cn.com/problems/longest-increasing-subsequence/

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

 

var lengthOfLIS = function(nums) {
 
    let n= nums.length
    if(n<2){
        return n
    }
    let max=1
    let dp=new Array()
    dp[0]=1
    for(let i=0;i<n;i++){
       dp[i]=1
       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
}

这道题是很经典「动态规划」算法问题。

需要对「子序列」和「子串」这两个概念进行区分;
子序列(subsequence):子序列并不要求连续,例如:序列 [4, 6, 5] 是 [1, 2, 4, 3, 7, 6, 5] 的一个子序列;
子串(substring、subarray):子串一定是原始字符串的连续子串。
题目中的「上升」的意思是「严格上升」。反例: [1, 2, 2, 3] 不能算作「上升子序列」;

首先考虑题目问什么,就把什么定义成状态。题目问最长上升子序列的长度,其实可以把「子序列的长度」定义成状态,但是发现「状态转移」不好做。

基于「动态规划」的状态设计需要满足「无后效性」的设计思想,可以将状态定义为「以 nums[i] 结尾 的「上升子序列」的长度」。

「无后效性」的设计思想:让不确定的因素确定下来,以保证求解的过程形成一个逻辑上的有向无环图。这题不确定的因素是某个元素是否被选中,而我们设计状态的时候,让 nums[i] 必需被选中,这一点是「让不确定的因素确定下来」,也是我们这样设计状态的原因。

1. 定义状态:

dp[i] 表示:以 nums[i] 结尾 的「上升子序列」的长度。注意:这个定义中 nums[i] 必须被选取,且必须是这个子序列的最后一个元素;

2. 状态转移方程:

如果一个较大的数接在较小的数后面,就会形成一个更长的子序列。只要 nums[i] 严格大于在它位置之前的某个数,那么 nums[i] 就可以接在这个数后面形成一个更长的上升子序列。

3. 初始化

dp[i] = 1,11 个字符显然是长度为 11 的上升子序列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值