【代码随想录】动态规划专题4(Python)

25.最长递增子序列

300.最长递增子序列
dp[i]表示前i个数中的最长递增子序列
dp[i]=max(0到i-1中比i小的dp[j]+1)

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        dp = [1]*len(nums)
        for i in range(1,len(nums)):
            for j in range(i):
                if nums[i]>nums[j]:
                    dp[i] = max(dp[i],dp[j]+1)
        print(dp)
        return max(dp)

26.最长连续递增序列

674. 最长连续递增序列
只与前一个值进行比较

class Solution:
    def findLengthOfLCIS(self, nums: List[int]) -> int:
        dp = [1]*len(nums)
        for i in range(1,len(nums)):
            if nums[i]>nums[i-1]:
                dp[i] = dp[i-1]+1
        print(dp)
        return max(dp)

27.最长重复子数组

718. 最长重复子数组
返回二维dp数组的全部最大值
初始化时多添一行0和一列0
若两个当前值相等,dp[i][j] = dp[i-1][j-1]+1

class Solution:
    def findLength(self, nums1: List[int], nums2: List[int]) -> int:
        r = 0
        dp = [[0]*(len(nums2)+1) for _ in range(len(nums1)+1)]
        for i in range(1,len(nums1)+1):
            for j in range(1,len(nums2)+1):
                if nums1[i-1]==nums2[j-1]:
                    dp[i][j] = dp[i-1][j-1]+1
            if max(dp[i])>r: r = max(dp[i])
        return r

28.最长公共子序列

1143.最长公共子序列
若两值相等,更新值为前面行和列中最大值+1

class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        r = [0]*(len(text1)+1)
        dp = [[0]*(len(text1)+1) for _ in range(len(text2)+1)]
        for i in range(1,len(text2)+1):
            for j in range(1,len(text1)+1):
                if text2[i-1]==text1[j-1]:
                    dp[i][j]=max(r[:j])+1
            for j in range(1,len(text1)+1):
                r[j] = max(dp[i][j],r[j])
        print(dp)
        return max(r)

29.不相交的线

1035.不相交的线
同28,即求最长公共子序列

class Solution:
    def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int:
        r = [0]*(len(nums1)+1)
        dp = [[0]*(len(nums1)+1) for _ in range(len(nums2)+1)]
        for i in range(1,len(nums2)+1):
            for j in range(1,len(nums1)+1):
                if nums2[i-1]==nums1[j-1]:
                    dp[i][j]=max(r[:j])+1
            for j in range(1,len(nums1)+1):
                r[j] = max(dp[i][j],r[j])
        print(dp)
        return max(r)

30.最大子序和

53. 最大子序和
dp[i] = max(dp[i-1]+nums[i],nums[i])

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        dp = [0]*len(nums)
        dp[0]=nums[0]
        for i in range(1,len(nums)):
            dp[i] = max(dp[i-1]+nums[i],nums[i])
        return max(dp)

31.判断子序列

392.判断子序列
最长公共子序列的值是否与较短字符串长度相等
若当前比较值相等,dp值为左上+1
若不相等,dp值为左

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        dp = [[0]*(len(t)+1) for _ in range(len(s)+1)]
        for i in range(1,len(s)+1):
            for j in range(1,len(t)+1):
                if s[i-1]==t[j-1]:
                    dp[i][j] = dp[i-1][j-1]+1
                else:
                    dp[i][j] = dp[i][j-1]
        return dp[-1][-1]==len(s)

32.不同的子序列

115.不同的子序列
若相同,带t[i]的子序列数+在s[:j]中删掉s[j]
若不相同,在s[:j]中删掉s[j]

class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        dp = [[0]*(len(s)+1) for _ in range(len(t)+1)]
        dp[0][0]=1
        for i in range(len(s)):
            dp[0][i+1]=1
        for i in range(1,len(t)+1):
            for j in range(1,len(s)+1):
                if t[i-1]==s[j-1]:
                    dp[i][j] = dp[i-1][j-1]+dp[i][j-1]
                else:
                    dp[i][j] = dp[i][j-1]
        return dp[-1][-1]

33.两个字符串的删除操作

583. 两个字符串的删除操作
构建二维dp数组时多加一行一列
初始化时,第一行及第一列为0123…
递推公式,相同时为左上,不同时为min(左上+2,左+1,上+1)

class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        dp = [[0]*(len(word1)+1) for _ in range(len(word2)+1)]
        for i in range(len(word1)):
            dp[0][i+1] = i+1
        for i in range(len(word2)):
            dp[i+1][0] = i+1
        for i in range(1,len(word2)+1):
            for j in range(1,len(word1)+1):
                if word2[i-1]==word1[j-1]:
                    dp[i][j]=dp[i-1][j-1]
                else:
                    dp[i][j]=min(dp[i-1][j-1]+2,dp[i-1][j]+1,dp[i][j-1]+1)
        return dp[-1][-1]

34.编辑距离

72. 编辑距离
若相同,和dp[i-1][j-1]一样
若不同,min(删,增,改)

class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        dp = [[0]*(len(word1)+1) for _ in range(len(word2)+1)]
        for i in range(1,len(word1)+1):
            dp[0][i]=i
        for i in range(1,len(word2)+1):
            dp[i][0]=i
        print(dp)
        for i in range(1,len(word2)+1):
            for j in range(1,len(word1)+1):
                if word2[i-1]==word1[j-1]:
                    dp[i][j]=dp[i-1][j-1]
                else:
                    dp[i][j]=min(dp[i-1][j-1]+1,dp[i][j-1]+1,dp[i-1][j]+1)
        print(dp)
        return dp[-1][-1]

35.回文子串

647. 回文子串
dp[i][j]表示s[i:j]是否回文
从后向前逐个作为分割点,i向前走,j向后走
s[i]==s[j]时,若ij相等或相邻,或s[i:j]回文,则回文串数量+1

class Solution:
    def countSubstrings(self, s: str) -> int:
        r = 0
        dp = [[False]*len(s) for _ in range(len(s))]
        for i in range(len(s)-1,-1,-1):
            for j in range(i,len(s)):
                if s[i]==s[j]:
                    if j-i<=1:
                        r += 1
                        dp[i][j] = True
                    elif dp[i+1][j-1]:
                        r += 1
                        dp[i][j] = True
        return r

36.最长回文子序列

516.最长回文子序列
dp[i][j]表示s[i:j]回文子序列数量
从后向前逐个作为分割点,i向前走,j向后走
s[i]==s[j]时,dp[i][j] = dp[i+1][j-1]+2,长度+2
s[i]!=s[j]时,dp[i][j] = max(dp[i][j-1],dp[i+1][j])
初始化,只有一个字母dp为1

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        dp = [[0]*len(s) for _ in range(len(s))]
        for i in range(len(s)):
            dp[i][i] = 1
        for i in range(len(s)-1,-1,-1):
            for j in range(i+1,len(s)):
                if s[i]==s[j]:
                    dp[i][j] = dp[i+1][j-1]+2
                else:
                    dp[i][j] = max(dp[i][j-1],dp[i+1][j])
        return dp[0][-1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值