概述
给定两个字符串,找出将一个字符串转换成另一个字符串的最少操作数。一个字符串可以通过执行以下三种操作转换为另一个字符串
-
插入
-
移除
-
替换
所有这些操作的成本都是一样的。 让我们来看看一些例子
例1:
First String: abc
Second String: abcd
Output: 1
我们可以在第一个字符串中插入一个**"d"**。
例2:
First String: abc
Second String: ab
Output: 1
我们可以从第一个字符串中删除 'c' 。
例3:
First String: abc
Second String: abd
Output: 1
我们可以用**"d "** 替换第一个字符串中的**"c"** 。
例4:
First String: abce
Second String: abd
Output: 2
-
我们可以从第一个字符串中删除**'e'**。
-
我们可以将第一个字符串中的'**c'**替换为'd'。
一些基本情况。假设第一个字符串的长度为m,第二个字符串的长度为n
-
如果第一个和第二个字符串的长度都是零,那么输出为0
-
如果只有第一个字符串是空的,那么输出是第二个字符串的长度
-
如果只有第二个字符串是空的,那么输出是第一个字符串的长度
否则,如果第一个和第二个字符串的最后一个字符匹配,那么输出是第一个字符串长度为m-1,第二个字符串长度为n-1的最小编辑操作。这意味着递归(m-1, n-1)如果最后的字符不匹配,那么我们可以在第一个字符串中进行插入、删除或替换选项。
-
替换 - 递归(m-1, n-1)
-
删除 - 递归(m,-1 n)
-
插入 - 递归(m, n-1)
递归解决方案
下面是同一问题的递归解决方案
package main
import (
"fmt"
"math"
)
func main() {
output := minDistance("abc", "abcd")
fmt.Println(output)
output = minDistance("abc", "ab")
fmt.Println(output)
output = minDistance("abc", "abd")
fmt.Println(output)
output = minDistance("abce", "abd")
fmt.Println(output)
}
func minDistance(word1 string, word2 string) int {
word1Rune := []rune(word1)
word2Rune := []rune(word2)
lenWord1 := len(word1Rune)
lenWord2 := len(word2Rune)
return minDistanceUtil(word1Rune, word2Rune, lenWord1, lenWord2)
}
func minDistanceUtil(word1 []rune, word2 []rune, lenWord1, lenWord2 int) int {
if lenWord1 == 0 && lenWord2 == 0 {
return 0
}
if lenWord1 == 0 {
return lenWord2
}
if lenWord2 == 0 {
return lenWord1
}
if word1[lenWord1-1] == word2[lenWord2-1] {
return minDistanceUtil(word1, word2, lenWord1-1, lenWord2-1)
} else {
x := minDistanceUtil(word1, word2, lenWord1-1, lenWord2-1)
y := minDistanceUtil(word1, word2, lenWord1, lenWord2-1)
z := minDistanceUtil(word1, word2, lenWord1-1, lenWord2)
return 1 + minOfThree(x, y, z)
}
}
func minOfThree(x, y, z int) int {
output := int(math.Min(float64(x), math.Min(float64(y), float64(z))))
return output
}
输出
1
1
1
2
如果你注意到上述程序,许多子问题被反复计算,因此上述解决方案的复杂性是指数级的。因此,我们也可以在这里使用动态编程来减少整个时间的复杂性。
下面是同样的程序
动态编程解决方案
package main
import (
"fmt"
"math"
)
func main() {
output := minDistance("abc", "abcd")
fmt.Println(output)
output = minDistance("abc", "ab")
fmt.Println(output)
output = minDistance("abc", "abd")
fmt.Println(output)
output = minDistance("abce", "abd")
fmt.Println(output)
}
func minDistance(word1 string, word2 string) int {
word1Rune := []rune(word1)
word2Rune := []rune(word2)
lenWord1 := len(word1Rune)
lenWord2 := len(word2Rune)
editDistanceMatrix := make([][]int, lenWord1+1)
for i := range editDistanceMatrix {
editDistanceMatrix[i] = make([]int, lenWord2+1)
}
for i := 1; i <= lenWord2; i++ {
editDistanceMatrix[0][i] = i
}
for i := 1; i <= lenWord1; i++ {
editDistanceMatrix[i][0] = i
}
for i := 1; i <= lenWord1; i++ {
for j := 1; j <= lenWord2; j++ {
if word1Rune[i-1] == word2Rune[j-1] {
editDistanceMatrix[i][j] = editDistanceMatrix[i-1][j-1]
} else {
editDistanceMatrix[i][j] = 1 + minOfThree(editDistanceMatrix[i-1][j], editDistanceMatrix[i][j-1], editDistanceMatrix[i-1][j-1])
}
}
}
return editDistanceMatrix[lenWord1][lenWord2]
}
func minOfThree(x, y, z int) int {
output := int(math.Min(float64(x), math.Min(float64(y), float64(z))))
return output
}
输出
1
1
1
2