在Go(Golang)中将一个字符串转换成另一个字符串的方法

290 阅读3分钟

概述

给定两个字符串,找出将一个字符串转换成另一个字符串的最少操作数。一个字符串可以通过执行以下三种操作转换为另一个字符串

  • 插入

  • 移除

  • 替换

所有这些操作的成本都是一样的。 让我们来看看一些例子

例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