Leetcode 72.编辑距离
1 题目描述(Leetcode题目链接)
给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')
2 题解
来分析一下这个单词,
w
o
r
d
1
=
h
o
r
s
e
word1=horse
word1=horse
w
o
r
d
2
=
r
o
s
word2=ros
word2=ros
我们令
i
,
j
i,j
i,j分别指向两个单词的最后一个位置,这里
i
→
e
,
j
→
s
i\rightarrow e, j\rightarrow s
i→e,j→s,如下图所示。
显然
i
,
j
i,j
i,j指向的字母不同,那么为了让字母能够相同,就有三种操作:
(1)插入:
w
o
r
d
1
word1
word1在
i
i
i所在的位置插入一个
s
s
s,那么最少操作数将由
h
o
r
s
e
horse
horse和
r
o
ro
ro产生,如下图所示。此时,
i
i
i不变,
j
=
j
−
1
j=j-1
j=j−1。
(2)删除:将
i
i
i所指向的字母删除,那么最少操作数将由
h
o
r
s
hors
hors和
r
o
s
ros
ros产生,如下图所示。此时
j
j
j不变,
i
=
i
−
1
i=i-1
i=i−1。
(3)替换:将
i
i
i所指的字母替换成
j
j
j所指的字母,那么最少操作数将由
h
o
r
s
hors
hors和
r
o
ro
ro产生,如下图所示。此时
i
=
i
−
1
,
j
=
j
−
1
i=i-1,j=j-1
i=i−1,j=j−1。
那么如果
i
,
j
i,j
i,j所指向的字母相同,那就不用做改动,将
i
,
j
i,j
i,j都左移一位就好了。
因此定义
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示将
w
o
r
d
1
word1
word1的前
i
i
i个字母变成
w
o
r
d
2
word2
word2的前
j
j
j个字母所需的最小操作次数,根据上面的分析,状态转移方程如下:
d
p
[
i
]
[
j
]
=
{
d
p
[
i
−
1
]
[
j
−
1
]
i
f
w
o
r
d
1
[
i
]
=
=
w
o
r
d
2
[
j
]
1
+
m
i
n
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
,
d
p
[
i
−
1
]
[
j
−
1
]
)
o
t
h
e
r
w
i
s
e
dp[i][j] = \begin{cases} dp[i-1][j-1]&if\ \ \ \ word1[i] == word2[j]\\ 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])&otherwise \end{cases}
dp[i][j]={dp[i−1][j−1]1+min(dp[i−1][j],dp[i][j−1],dp[i−1][j−1])if word1[i]==word2[j]otherwise
多加一行一列,便于处理空字符串的情况。
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
m, n = len(word1), len(word2)
dp = [([0]*(n+1)) for _ in range(m+1)]
for i in range(1, m+1): #初始化第一列
dp[i][0] = i
for j in range(1, n+1): #初始化第一行
dp[0][j] = j
for i in range(1, m+1):
for j in range(1, n+1):
if word1[i-1] == word2[j-1]:
dp[i][j] = dp[i-1][j-1]
else:
dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1])
return dp[m][n]