1. 程式人生 > >動態規劃常見題(Python)

動態規劃常見題(Python)

由於動態規劃一直是一個比較難的點,因此在這裡將leetcode刷題過程中碰到的比較常見的動態規劃題記錄下來。不定期更新。

1.最長迴文子串

給定一個字串 s,找到 s 中最長的迴文子串。你可以假設 的最大長度為1000。

輸入: "babad"
輸出: "bab"
注意: "aba"也是一個有效答案。

先上程式碼:

class Solution(object):
    def longestPalindrome(self, s):
        tempstr=res=[]
        for i in range(len(s)):
            #odd
            tempstr=self.longestPalindromeHelp(s,i,i)
            if len(tempstr)>len(res):
                res=tempstr
            #even
            tempstr=self.longestPalindromeHelp(s,i,i+1)
            if len(tempstr)>len(res):
                res=tempstr
        return res

    def longestPalindromeHelp(self,s,l,r):
        while l>=0 and r<len(s) and s[l]==s[r]:
            l-=1
            r+=1
        return s[l+1:r]

思路:從字串的中間開始比較,若兩字元相等,則同時向外移動一位,繼續比較。需要注意的是,從中間開始需要分字串為奇數和字串為偶數兩種情況。

2.最長公共字串和最長公共子序列

字串和子序列的區別在於字串要求字元必須是連續的,而子序列不要求連續。

最長公共字串的程式碼如下:

def find_substr(str1,str2):
    dp=[[0 for j in range(len(str2)+1)] for i in range(len(str1)+1)]
    maxlen=0
    for i in range(len(str1)):
        for j in range(len(str2)):
            if str1[i]==str2[j]:
                dp[i+1][j+1]=dp[i][j]+1
                if dp[i+1][j+1]>maxlen:
                    maxlen=dp[i+1][j+1]
                    index=i
    return maxlen,str1[index+1-maxlen:index+1]

最長公共子序列的遞迴公式如下:

程式碼如下:

def find_subseq(str1,str2):
    dp=[[0 for j in range(len(str2)+1)] for i in range(len(str1)+1)]
    ans=''
    for i in range(len(str1)):
        for j in range(len(str2)):
            if str1[i]==str2[j]:
                dp[i+1][j+1]=dp[i][j]+1
                ans+=str1[i]
            else:
                dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1])
    return dp[-1][-1],ans

需要指出的是該程式碼只能用於兩字串僅有一個最長公共子序列的情況。如果碰到如‘ABCBDAB’,‘BDCABA’會失效。

3.最長遞增子序列(LIS)

複雜度為O(n^2)的方法:

class Solution(object):
    def lengthOfLIS(self, nums):
        if not nums:
            return 0
        dp=[1]*len(nums)
        for i in range(len(nums)):
            for j in range(i):
                if nums[i]>nums[j]:
                    dp[i]=max(dp[i],dp[j]+1)
        return max(dp)