代码随想录算法训练营第四十四天 |动态规划part11

73 阅读3分钟

代码随想录算法训练营第四十四天 |动态规划part11

1143 最长公共子序列

image-20250124115942990.png

思路:和上一题最长重复子数组几乎一样,区别就在于是否连续,上一题要求连续,这一题不要求连续,所以说就需要进行一个else的判断,dp[i] [j] 的值应该是dp[i-1] [j] 和 dp[i] [j-1]的最大值,需要前一次的结果。

# text1 = "abcde"
# text2 = "ace" 
​
dp = [[0] * (len(text2) + 1) for _ in range(len(text1) + 1)]
​
# dp[i][j] 表示以i-1为结尾的text1 和 以j-1为结尾的text2 的最长公共子序列长度
result = 0
for i in range(1, len(text1) + 1):
    for j in range(1, len(text2) + 1):
        if text1[i-1] == text2[j-1]:
            dp[i][j] = dp[i-1][j-1] + 1
        else:
            dp[i][j] = max(dp[i-1][j], dp[i][j-1])
        result = max(result, dp[i][j])
return result

1035 不相交的线

image-20250124120000649.png

思路:和上一题一模一样,就是求最长公共子序列

dp = [[0] * (len(nums2)+1) for _ in range(len(nums1)+1)]
result = 0
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
        else :
            dp[i][j] = max(dp[i-1][j],dp[i][j-1])
        if result < dp[i][j]:
            result = dp[i][j]
return result

53 最大子数组和

image-20250124120022352.png

思路:dp[i] [j]保存对应的和。代码如下:会超时,因为有2层for循环

# nums = [5,4,-1,7,8]# dp[i][j] 以i为开头 j为结尾的子数组的最大和
if len(nums) == 1:
    return nums[0]
dp = [[float('-inf') for _ in range(len(nums))] for _ in range(len(nums))]
result = float('-inf')
for i in range(len(nums)):
    sum_ = 0
    for j in range(i,len(nums)):
        sum_ += nums[j]
        dp[i][j] = max(dp[i][j-1],sum_)
        if result < dp[i][j]: result = dp[i][j]
return (result)

dp[i] = max(dp[i-1]+nums[i-1],nums[i-1])

指的是,前i个数的最大子数组和,是由前i-1个数的最大子数组和 + 第i个数(nums[i-1]) 第i个数进行比较的出来的。

可能前i-1个数和为负数,也可能为正数,所以都需要考虑。

本人代码:

# nums = [-2,1,-3,4,-1,2,1,-5,4]
# dp[i] 表示前i个数组的最大子数组和
dp = [0] * (len(nums)+1)
# dp[0] = float('-inf')
result = nums[0]
for i in range(1,len(nums)+1):
    dp[i] = max(dp[i-1]+nums[i-1],nums[i-1])
    result = max(result,dp[i])
# print(result)
return result

392 判断子序列

image-20250124120040344.png

思路:感觉和最长公共子序列差不多,只需要返回的长度等于短的字符串的长度即可。

dp = [[0]*(len(t)+1) for i in range(len(s)+1)]
result = 0
for i in range(len(s)):
    for j in range(len(t)):
        if s[i] == t[j]:
            dp[i][j] = dp[i-1][j-1] + 1
        else :
            dp[i][j] = max(dp[i-1][j],dp[i][j-1])
        if result < dp[i][j]:
            result = dp[i][j]
return result == len(s)
​

参考代码:

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]
if dp[-1][-1] == len(s):
    return True
return False