300. 最长递增子序列

  1. 最长递增子序列
    给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
    子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

示例 2:
输入:nums = [0,1,0,3,2,3]
输出:4

示例 3:
输入:nums = [7,7,7,7,7,7,7]
输出:1

解题思路:
序列a=[10,9,2,5,3,7,101,18,20]
方法一 :动态规划
思路:先选择一个数字,如选择7,则7 前面上升是2 3 7或者2 5 7,即到7为止最长子序列的长度为3
第一步:状态转移方程
DP[i] 表示从0->i元素,且要把i元素要选上,的最长子序列的长度。(如上面选择的7,则DP[i]为3)
**问题转换为求:**Max(DP[0]、DP[1]…DP[n-1]) 即LIS length =max(dp[i]),其中0≤i<n
如DP[0]是10,最长上升序列为10
DP[1]是9, 最长上升序列为9
DP[2]是2, 最长上升序列为2
DP[3]是5, 最长上升序列为2 5
DP[4]是3, 最长上升序列为2 5 或2 3
DP[5]是7, 最长上升序列为2 3 7或2 5 7
DP[6]是101, 最长上升序列为2,3,7,101或2,5,7,101
DP[7]是18, 最长上升序列为2 3 7 18或2,5,7,18
DP[8]是20, 最长上升序列为2 3 7 18 20 或2 5 7 18 20
所以Max(DP[0]、DP[1]…DP[n-1])即Max([1, 1, 1, 2, 2, 3, 4, 4, 5]) 是5

第2步:状态转移方程DP[i]
for i i范围为0->n-1
DP[i]=Max{DP[j]+1} =Max{DP[j]}+1 注:j范围是0->i-1且a[j]<a[i] 意思是j是i前面的数所以j的范围是[0,i-1],又因为要求是上升子序列所以需要a[j]<a[i],a[i]为7则a[j]可以是2 5 3但不可以是10 9;+1这个1指的是a[i]这个元素本身如是7
即2层循环
i:0->n-1:
j:0->i-1:
求DP[i]
所以时间复杂度是O(N平方)

def lengthOfLIS(nums):
    if not nums:
        return 0
    dp = []
    for i in range(len(nums)):
        print("====i:",i)
        dp.append(1)
        for j in range(i):
            print("**j:", j)
            if nums[i] > nums[j]:
                print("i:%s,dp[i]:%s"%(i,dp[i]))
                print("j:%s,dp[j]:%s"%(j,dp[j]))
                dp[i] = max(dp[i], dp[j] + 1)#这里+1的1指的是第i个元素本身,意思是
                #当如当i为5时,即元素是7,则满足if条见j取2、3、4对应的元素为2、5、3
                #则dp[5]=max(dp[5],dp[2]+1,dp[3]+1,dp[4]+1)
                #dp[i] = max(dp[j] + 1)这么写是不对的
                print("last i:%s,dp[i]:%s"%(i,dp[i]))
        print("i&&:",dp)
    print(dp)#[1, 1, 1, 2, 2, 3, 4, 4, 5]
    return max(dp)


nums=[10,9,2,5,3,7,101,18,20]
a=lengthOfLIS(nums)
print(a)#5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值