题目:给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行三种操作:插入一个字符,删除一个字符,替换一个字符。
动态规划标准步骤:
1. 找确定状态
dp[n][m] 表示word1的n个字符与word2的m个字符的编辑距离,由于存在0长度的情况,所以应该用dp[n+1][m+1] 表示word1的n个字符与word2的m个字符的编辑距离
2. 定义子问题
a、b字符一共有三种操作方式,a增加一个字符,b增加一个字符(相当于a减少一个字符),a或b替换一个字符
那么dp[i][j]的前一步操作有
a增加一个字符dp[i-1][j],操作数+1
b增加一个字符dp[i][j-1],操作数+1
a或b替换一个字符dp[i-1][j-1]
a或b替换一个字符有两种情况:1)a[i-1] 等于 b[i-1],则当前相等,不需要额外操作
2)a[i-1] 不等于 b[i-1], 则当前不等,进行一次替换操作
则,dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]) if a[i-1] 等于 b[i-1] else min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+1)
3. 初始条件和确定边界
初始当i等于0时,a要与b相等则需执行j步插入操作
j等于0同理
4.确定计算顺序
从最小下标开始赋值
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
n, m = len(word1), len(word2)
# !注意有一个word为空的情况
if n*m == 0:
return n + m
dp = [[0] * (m+1) for _ in range(n+1)]
# 初始化边界,当i或者j为0的时候,即有一个word长度为0时
for i in range(n+1):
dp[i][0] = i
for j in range(m+1):
dp[0][j] = j
for i in range(1, n+1):
for j in range(1, m+1):
# 三种情况,a插入一个,b插入 一个(等同于a删除一个),a替换一个(或者b替换一个)
# 特别注意替换的情况有两种,当word1[i-1] == word2[j-1],即当前最后一位word(注意下标)相等时,dp[i][j] = dp[i-1][j-1],
# 否则替换的情况为dp[i-1][j-1]+1
left = dp[i-1][j] + 1
up = dp[i][j-1] + 1
left_up = dp[i-1][j-1]
if word1[i-1] != word2[j-1]:
left_up += 1
dp[i][j] = min(left, up, left_up)
return dp[-1][-1]