题目描述
给你两个单词 word1
和 word2
, 请返回将 word1
转换成 word2
所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
- 插入一个字符
- 删除一个字符
- 替换一个字符
示例 1:
输入: word1 = “horse”, word2 = “ros”
输出: 3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)
示例 2:
输入: word1 = “intention”, word2 = “execution”
输出: 5
解释:
intention -> inention (删除 ‘t’)
inention -> enention (将 ‘i’ 替换为 ‘e’)
enention -> exention (将 ‘n’ 替换为 ‘x’)
exention -> exection (将 ‘n’ 替换为 ‘c’)
exection -> execution (插入 ‘u’)
提示:
- 0 <= word1.length, word2.length <= 500
- word1 和 word2 由小写英文字母组成
代码及注释
func minDistance(word1 string, word2 string) int {
m, n := len(word1), len(word2)
// 创建一个二维数组dp,dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最少操作次数
dp := make([][]int, m + 1)
for i := range dp {
dp[i] = make([]int, n + 1)
}
// 初始化边界条件
for i := 0; i <= m; i++ {
dp[i][0] = i // 当word2为空时,需要删除word1的所有字符
}
for j := 0; j <= n; j++ {
dp[0][j] = j // 当word1为空时,需要插入word2的所有字符
}
// 动态规划填表
for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
if word1[i - 1] == word2[j - 1] {
dp[i][j] = dp[i - 1][j - 1] // 如果当前字符相同,不需要进行任何操作
} else {
// 如果当前字符不同,考虑三种操作(插入、删除、替换)的最小值,并加1
dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1
}
}
}
return dp[m][n] // 返回将word1转换为word2所需的最小操作次数
}
// 辅助函数,返回两个整数中的较小值
func min(a, b int) int {
if a < b {
return a
}
return b
}
代码解释
这里使用动态规划来解决编辑距离问题的思路是基于以下的逻辑:
编辑距离问题可以通过三种基本操作得到:插入(Insert)、删除(Delete)和替换(Replace)。给定两个字符串word1
和word2
,我们希望找到最少的操作次数,将word1
转换为word2
。
动态规划的核心思想是将大问题分解为小问题,然后逐步解决这些小问题。在这个问题中,我们需要找到将word1
的前i
个字符转换为word2
的前j
个字符所需的最少操作次数。
具体实现如下:
// 初始化动态规划数组,dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最少操作次数
for i := 0; i <= m; i++ {
dp[i][0] = i // 当word2为空时,需要删除word1的所有字符
}
for j := 0; j <= n; j++ {
dp[0][j] = j // 当word1为空时,需要插入word2的所有字符
}
上面的初始化是基于以下逻辑:
- 当
word2
为空,word1
变为word2
需要删除word1
的所有字符,所以需要i
次删除操作。 - 当
word1
为空,word1
变为word2
需要插入word2
的所有字符,所以需要j
次插入操作。
接下来,我们需要填充动态规划数组dp
:
for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
if word1[i - 1] == word2[j - 1] {
dp[i][j] = dp[i - 1][j - 1] // 如果当前字符相同,不需要进行任何操作
} else {
// 如果当前字符不同,考虑三种操作(插入、删除、替换)的最小值,并加1
dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1
}
}
}
这里的逻辑是:
- 如果
word1[i-1]
和word2[j-1]
相同,则dp[i][j]
等于dp[i-1][j-1]
,因为不需要进行任何操作。 - 如果
word1[i-1]
和word2[j-1]
不同,则dp[i][j]
等于dp[i-1][j]
(删除操作)、dp[i][j-1]
(插入操作)和dp[i-1][j-1]
(替换操作)三者中的最小值,然后再加1。
最终,dp[m][n]
就是将word1
转换为word2
所需的最小操作次数。
这样的动态规划方法能够高效地找到最小的编辑距离,其时间复杂度为O(m × n),其中m和n分别是word1
和word2
的长度。