动态规划(二)

最长序列型动态规划

Longest Increasing Subsequence

f(i) f ( i ) :以 nums[i] n u m s [ i ] 为结尾的最长上升子序列的长度

f(i)=maxj<i,nums[j]<nums[i]f(j)+1 f ( i ) = m a x j < i , n u m s [ j ] < n u m s [ i ] f ( j ) + 1

class Solution:
    """
    @param nums: An integer array
    @return: The length of LIS (longest increasing subsequence)
    """
    def longestIncreasingSubsequence(self, nums):
        # write your code here
        if not nums:
            return 0
        length=[1]*len(nums)

        for i in range(len(nums)):
            j=0
            while j<i:
                if nums[j]<nums[i]:
                    length[i]=max(length[j]+1,length[i])
                j=j+1

        return max(length)

Russian Doll Envolopes

先按一维排序,即先按长度排序

f(i)=maxj<ilengthj<lengthiwidthj<lengthif(j)+1 f ( i ) = max j < i l e n g t h j < l e n g t h i w i d t h j < l e n g t h i f ( j ) + 1

如果按长度从小到大,宽度从大到小,相当于求宽度的最长上升子序列。
时间复杂度为 O(n2) O ( n 2 ) ,time exceeded。

class Solution:
    """
    @param: envelopes: a number of envelopes with widths and heights
    @return: the maximum number of envelopes
    """
    def maxEnvelopes(self, envelopes):
        # write your code here
        if not envelopes:
            return 0
        if not envelopes[0]:
            return 0
        envelopes=sorted(envelopes,key=lambda x:(x[0],x[1]))
        nums=[1]*len(envelopes)

        for i in range(len(nums)):
            j=0
            while j <i:
                # Ej能放到Ei里
                if envelopes[j][1]<envelopes[i][1] and envelopes[j][0]<envelopes[i][0]:
                    nums[i]=max(nums[j]+1,nums[i])
                j=j+1        
        return max(nums)

划分型动态规划

这里写图片描述
这里写图片描述

Perfect Squares

f(i) f ( i ) 表示 i i 最少被分为几个完全平方数之和

f(i)=min1ij2n(f(ijj))+1

class Solution:
    """
    @param n: a positive integer
    @return: An integer
    """
    def numSquares(self, n):
        # write your code here
        if not n:
            return 0
        nums=[i for i in range(n+1)]
        for i in range(1,n+1):
            if i>=2:
                j=1
                while j*j<=i:
                    nums[i]=min(nums[i-j*j]+1,nums[i])
                    j=j+1

        return nums[-1]

palindrome partitioning

f(i) f ( i ) 记录 s[0:i] s [ 0 : i ] 最少划分为几个回文串(不包括 s[i] s [ i ]

f[i]=mins[j:i]is a palindromej=0,,i1(f[j])+1 f [ i ] = min s [ j : i ] is a palindrome j = 0 , ⋯ , i − 1 ( f [ j ] ) + 1

确定状态:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

如何判断回文串?
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

class Solution:
    """
    @param s: A string
    @return: An integer
    """
    def minCut(self, s):
        n=len(s)
        # write your code here
        if not s:
            return 0


        isPalin=[[0]*n for i in range(n)]
        #记录原始序列中所有回文串
        for t in range(n):
            #所有奇数回文串
            x=t
            y=t
            while x>=0 and y<=n-1 and s[x]==s[y]:
                isPalin[x][y]=True
                x=x-1
                y=y+1


            #所有偶数回文串
            x=t
            y=t+1
            while x>=0 and y<=n-1 and s[x]==s[y]:
                isPalin[x][y]=True
                x=x-1
                y=y+1

        state=[i for i in range(len(s)+1)]
        for i in range(1,len(s)+1):
            for j in range(i):
                if isPalin[j][i-1]:
                    state[i]=min(state[j]+1,state[i])

        return state[-1]-1

Copy books

f[k][i] f [ k ] [ i ] 记为第 k k 个人最少需要多少时间抄完i本书:

f[k][i]=minj=0,,imax(f[k1][j],A[j]++A[i1]) f [ k ] [ i ] = min j = 0 , ⋯ , i max ( f [ k − 1 ] [ j ] , A [ j ] + ⋯ + A [ i − 1 ] )

j=i j = i 表明第 k k 个人不抄书。
这个题下标有点搞不清楚。。。

博弈型动态规划

Coins in a line

确定状态
f(i)表示先手面对 i i <script type="math/tex" id="MathJax-Element-25">i</script>个石子时是必胜还是必败:

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

class Solution:
    """
    @param n: An integer
    @return: A boolean which equals to true if the first player will win
    """
    def firstWillWin(self, n):
        # write your code here

        res=[False]*(n+1)
        for i in range(1,n+1):
            if i<=2:
                res[i]=True
            else:
                if res[i-1]==1 and res[i-2]==1:
                    res[i]=False
                else:
                    res[i]=True

        return res[-1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值