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

62 阅读3分钟

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

115 不同的子序列

image-20250124215320946.png

  • 确定dp数组以及下标的含义

    • dp[i] [j] 以i-1为结尾的s中有以j-1为结尾的t的个数为dp[i] [j]
    • 方便dp数组进行初始化操作
  • 递推公式

    • if s[i-1] == t[j-1]:

      遇到相同的情况,考虑使用不使用s[i-1],如果使用,那么就是dp[i-1] [j-1];如果不使用,那就是dp[i-1] [j]

      dp[i] [j] = dp[i-1] [j-1] : 表示 第i个和第j个相同,所以就是前i-1,j-1个中包含t的个数

      dp[i] [j] = dp[i-1] [j]:表示第i个和第j个相同,但是第不使用第i个数,bagg -> bag 不使用前者的第二个g。

      dp[i] [j] = dp[i-1] [j-1] + dp[i-1] [j]

      else:

      就是不考虑这个元素,模拟把这个元素删除掉,不使用这个元素,只在s里面删除

      dp[i] [j] = dp[i-1] [j]

  • dp数组如何初始化

    • 初始化第一行,第一列 dp[i] [0] = 1, dp[0] [j] = 0 ,dp[0] [0] = 1

代码如下:

# s = "babgbag"
# t = "bag"
dp = [[0]*(len(t)+1) for i in range (len(s)+1)]
for i in range(len(s)):
    dp[i][0] = 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] + dp[i-1][j]
        else :
            dp[i][j] = dp[i-1][j]
# print(dp[-1][-1])
return dp[-1][-1]
​

583 两个字符串的删除操作

image-20250124215338400.png

  • 确定dp数组以及下标的含义

    • dp[i] [j] 以i-1为结尾的word1 和以 j-1 为结尾的word2 为相同最少操作次数为 dp[i] [j]
  • 递推公式

    • if word1[i-1] == word2[j-1]:

      dp[i] [j] = dp[i-1] [j-1]

      else :

      dp[i] [j] = dp[i-1] [j] (不考虑word1[i-1]了) + 1 (模拟把word1[i-1]删除)

      dp[i] [j] = dp[i] [j-1] + 1 (模拟把word2[j-1]删除)

      dp[i] [j] = dp[i-1] [j-1] + 2 (模拟把word1[i-1],word2[j-1]都删除)

      dp[i] [j] = min(dp[i-1] [j]+1,dp[i] [j-1] + 1,dp[i-1] [j-1]+2)

  • dp数组如何初始化

    • 初始化第一行第一列,
    • 第一列 dp[i] [0] = i
    • 第一行 dp[0] [j] = j

代码:

dp = [[0]*(len(word2)+1) for i in range(len(word1)+1)]
for i in range(len(word1)+1):
    dp[i][0] = i
for j in range(len(word2)+1):
    dp[0][j] = j
for i in range(1,len(word1)+1):
    for j in range(1,len(word2)+1):
        if word1[i-1] == word2[j-1]:
            dp[i][j] = dp[i-1][j-1]
        else :
            dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+2)
return dp[-1][-1]

72 编辑距离

image-20250124215349810.png

  • 确定dp数组以及下标的含义

    • dp[i] [j] : 以i-1 为结尾的word1 和以j-1 为结尾的word2 最少的操作次数为dp[i] [j]
  • 递推公式

    • if word1[i-1] == word2[j-1]:

      dp[i] [j] = dp[i-1] [j-1]

      else :

      增 dp[i-1] [j] + 1 dp[i] [j-1] + 1

      删 dp[i-1] [j] + 1 dp[i] [j-1] + 1

      替 dp[i-1] [j-1] + 1

      dp[i] [j] = min(dp[i-1] [j] + 1 , dp[i] [j-1] + 1 , dp[i-1] [j-1] + 1 )

dp = [[0]*(len(word2)+1) for i in range(len(word1)+1)]
for i in range(len(word1)+1):
    dp[i][0] = i
for j in range(len(word2)+1):
    dp[0][j] = j
for i in range(1,len(word1)+1):
    for j in range(1,len(word2)+1):
        if word1[i-1] == word2[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)
return dp[-1][-1]