• 求解最大升序子序列问题(动态规划)


    最大升序子序列:给定数组 [1,7,3,5,9,4,8],则该数组的最大升序子序列为 1,3,5,9,不要求连续。

    dp[i]存储第i个位置时,最大升序子序列的长度。

    状态转移方程:dp[i] = dp[j] + 1  , dp[j] = max(dp[0,i-1]) 

    初始状态dp[i]=1

    求解最大升序子序列长度不像是正规的动态规划问题,每次求解dp[i] 都需要遍历索引 i 之前的数组元素。

    具体的,如何求解以 i 结尾的数组的最大升序子序列长度。

    遍历arr[  0 :  i ] 内部的数组

    若存在 元素 满足arr[j]<arr[i] 且 lis[j]+1 > lis[i] ,

    then   lis[i] = list[j] +1

    def LIS(arr):
        if not arr or len(arr)==1:
            return 1
        dp = [0 for _ in range(len(arr))]
        for i in range(len(arr)):
            dp[i] = 1
            for j in range(i):
                if arr[j] < arr[i] and dp[j]+1>dp[i]:
                    dp[i] = dp[j]+1
        return dp[-1]

     贪心算法+二分优化  复杂度O(nlog2n)

    对于nlog2n的解法,此时的数组dp[i]的含义为以i结尾的最大升序子序列,注意此时的dp是动态更新的。当遍历到数组元素arr[i]时,若arr[i]小于dp[i],则在dp中寻找到arr[i]存放的位置并覆盖。注意到覆盖掉dp中原来的元素并不影响此时dp的长度,即之前找到的最大升序子序列长度依然是dp的长度。但为什么要覆盖掉呢?因为只有覆盖掉那个较大的元素,当后面还有更小且更长的升序序列时,这些序列才会被加到dp当中。(不知道说清楚了没有,没看懂的话直接看例子吧)

    找一个容易理解的例子:arr 1 3 2 4 5 2 2 2  。 它的最大升序子序列为  1 2  2  2 2

    此时的dp数组存储过程,遍历arr

    dp:  1

    dp:  1  3     (arr[1]比dp中最后一个元素1大,直接追加)

    dp:  1  2       (arr[2]比dp中最后一个元素3小,通过二分法找到arr[2]的位置并覆盖)

    dp:  1  2  4

    dp:  1  2  4  5

    dp:  1  2  2  5  (arr[5]比dp中最后一个元素5小,找到dp中arr[5]的位置并覆盖)

    dp:  1  2  2  2

    dp:  1  2  2  2  2

     1  def LIS(self,arr):
     2      n = len(arr)
     3      dp = [arr[0]]
     4      for i in range(1,n):
     5          if arr[i]>=dp[-1]:
     6              dp.append(arr[i])
     7          else:
     8              l,r = 0,len(dp)-1
     9              while l<r:
    10                  mid = (l+r)//2
    11                  if dp[mid]>arr[i]:
    12                      r = mid-1
    13                  else:
    14                      l = mid+1
    15              dp[l] = arr[i]
    16      return len(dp)

    附上代码 python

  • 相关阅读:
    P24—动态数组没有{}
    JavaB站学习————接口在开发中的作用
    JavaB站学习————extends和implements同时出现
    JavaB站学习————一个类可以实现多个接口以及接口的总结
    JavaB站学习————接口和多态联合使用。
    01日语五十音
    07 递归&&命名风格&&作业(结构体,malloc,函数,递归)
    JavaB站学习——作业16
    电子书
    破解压缩包
  • 原文地址:https://www.cnblogs.com/bianque/p/13525186.html
Copyright © 2020-2023  润新知