Day 50 动态规划 part16
2道题目
583. 两个字符串的删除操作
72. 编辑距离
解题理解
583
dpij:以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。
当word1i - 1 与 word2j - 1相同的时候,dpij = dpi - 1j - 1;
当word1i - 1 与 word2j - 1不相同的时候,有三种情况:
情况一:删word1i - 1,最少操作次数为dpi - 1j + 1
情况二:删word2j - 1,最少操作次数为dpij - 1 + 1
情况三:同时删word1i - 1和word2j - 1,操作的最少次数为dpi - 1j - 1 + 2
那最后当然是取最小值,所以当word1i - 1 与 word2j - 1不相同的时候,递推公式:dpij = min({dpi - 1j - 1 + 2, dpi - 1j + 1, dpij - 1 + 1});
因为 dpij - 1 + 1 = dpi - 1j - 1 + 2,所以递推公式可简化为:dpij = min(dpi - 1j + 1, dpij - 1 + 1);
这里可能不少录友有点迷糊,从字面上理解 就是 当 同时删word1i - 1和word2j - 1,dpij-1 本来就不考虑 word2j - 1了,那么我在删 word1i - 1,是不是就达到两个元素都删除的效果,即 dpij-1 + 1。
javascript
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
l1 = len(word1)
l2 = len(word2)
dp = [[0] * (l2 + 1) for _ in range(l1 + 1)]
for i in range(l2 + 1):
dp[0][i] = i
for i in range(l1 + 1):
dp[i][0] = i
for i in range(1, l1 + 1):
for j in range(1, l2 + 1):
if word1[i - 1] == word2[j - 1]:
dp[i][j] = dp[i - 1][j - 1]
else:
dp[i][j] = min(dp[i][j - 1] + 1, dp[i - 1][j] + 1, dp[i - 1][j - 1] + 2)
return dp[-1][-1]
72
dpij 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dpij。
if (word1i - 1 == word2j - 1) 那么说明不用任何编辑,dpij 就应该是 dpi - 1j - 1,即dpij = dpi - 1j - 1;
if (word1i - 1 != word2j - 1):
操作一:word1删除一个元素,那么就是以下标i - 2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 再加上一个操作。
即 dpij = dpi - 1j + 1;
操作二:word2删除一个元素,那么就是以下标i - 1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 再加上一个操作。
即 dpij = dpij - 1 + 1;
word2添加一个元素,相当于word1删除一个元素,例如 word1 = "ad" ,word2 = "a",word1删除元素'd' 和 word2添加一个元素'd',变成word1="a", word2="ad", 最终的操作数是一样!
操作三:替换元素,word1替换word1i - 1,使其与word2j - 1相同,此时不用增删加元素。
可以回顾一下,if (word1i - 1 == word2j - 1)的时候我们的操作 是 dpij = dpi - 1j - 1 对吧。
那么只需要一次替换的操作,就可以让 word1i - 1 和 word2j - 1 相同。
所以 dpij = dpi - 1j - 1 + 1;
综上,当 if (word1i - 1 != word2j - 1) 时取最小的,即:dpij = min({dpi - 1j - 1, dpi - 1j, dpij - 1}) + 1;
javascript
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
l1 = len(word1)
l2 = len(word2)
dp = [[0] * (l2 + 1) for _ in range(l1 + 1)]
for i in range(l2 + 1):
dp[0][i] = i
for i in range(l1 + 1):
dp[i][0] = i
for i in range(1, l1 + 1):
for j in range(1, l2 + 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], dp[i - 1][j]) + 1
return dp[-1][-1]