zoukankan      html  css  js  c++  java
  • leetcode算法刷题(五)——动态规划(三)

    今天的题目不是leetcode上面的。只是觉得动态规划还是不算很熟练,就接着找了点DP的题练练

    最长递增子序列的长度

    题目的意思:传入一个数组,要求出它的最长递增子序列的长度。例如:如在序列1,-1,2,-3,4,-5,6,-7中,最长递增序列为1,2,4,6,所以长度为4。
    分析:这道题我们可以用动态规划来做。对于数组的前i个元素,记L(i)为前i个最长递增子序列的长度。我们可以得到状态转移方程:L(i) = max(L(j))+1, 其中j<i, a[j]<a[i]. 这个解法比较容易想出来。可是这个解法的时间复杂度有点高(O(n^2))。下面是另一种解法,利用了二分查找(O(logn)),时间复杂度是O(nlogn)

    def maxlong(li):
        maxLong = [0 for i in range(len(li))]
        maxLong[0] = li[0]
        leng = 1
        
        for i in range(1,len(li)):
            if li[i] > maxLong[leng-1]:
                maxLong[leng] = li[i]
                leng += 1
            else:
                pos = biSearch(li[i], leng, maxLong)
                maxLong[pos] = li[i]
        return leng
    
    def biSearch(value, length, maxLong):
        left = 0
        right = length-1
        while left <= right:
            mid = (left+right)//2
            if maxLong[mid] > value:
                right = mid-1
            elif maxLong[mid] < value:
                left = mid+1
            else:
                return mid
        return left
    

    从左往右递增再递减的数列

    题目的意思:从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的。
    分析:这道题是上面那道题的变体。我们可以把这道题这样看:

    筛除数字后,数组的0~i位是递增数列,数组的(len(li)-1)~i位是递增数列。
    

    其实这道题等效于求出这两个数列的递增数列长度(a[i],b[i]),再求出min(len(li)-a[i]-b[i]+1)
    该方法利用了前一道题求最长递增子序列长度的方法。

    def maxlong(li):
        maxLong = [0 for i in range(len(li))]
        maxLong[0] = li[0]
        leng = 1
        
        for i in range(1,len(li)):
            if li[i] > maxLong[leng-1]:
                maxLong[leng] = li[i]
                leng += 1
            else:
                pos = biSearch(maxLong, leng, li[i])
                maxLong[pos] = li[i]
        return leng
    
    def biSearch(li, length, value):
        left = 0
        right = length-1
        while left <= right:
            mid = (right + left)//2
            if li[mid] > value:
                right = mid -1
            elif li[mid] < value:
                left = mid + 1
            else:
                return mid
        return left
    
    def mindelete(li):
        a = [0 for i in range(len(li))]
        b = [0 for i in range(len(li))]
        c = 0
        
        for i in range(len(li)):
            li_a = li[:i+1]
            a[i] = maxlong(li_a)
    
            li_b = li[:i:-1]+[li[i]]
            b[i] = maxlong(li_b)
           
        for i in range(len(li)):
            c = max(c, a[i]+b[i])
    
        return len(li) -c +1
    
  • 相关阅读:
    canvas,画个纸飞机
    时钟
    去除滚动条,内容仍然可以滚动
    鼠标指针移入移出改变图片透明度
    Mysql数据库优化总结
    一次利用nginx漏洞的木马事件
    一个批量删除大表数据的shell小脚本
    MegaCli监控raid卡磁盘信息以及相关的shell脚本
    MYSQL delete语句不支持别名?
    一次Mysql数据库服务器磁盘空间满引发的写入和同步问题
  • 原文地址:https://www.cnblogs.com/eric-nirnava/p/dynamic3.html
Copyright © 2011-2022 走看看