LeetCode72:编辑距离

问题72:给定两个单词word1word2,求出将word1转换成word2所使用的最少操作数。
你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

这题再一次展示了动态规划的强大。看上去毫无头绪的问题,用动态规划方法可以轻松解决。

定义一个len(word1)*len(word2)的二维数组dp,其中第i行第j列dp[i][j]表示将word1的前i个字符转换为word2的前j个字符需要的最少操作数。
初始化条件:dp[i][0] = idp[0][j] = j,这个很显然,把一个长度为i的单词转换为长度为0的单词需要删除i次,把一个长度为0的单词转换为长度为j的单词需要插入j次。
状态转移方程:本题状态转移方程为重点,共有四种情况。

  • 情况一:通过插入一个字符,使得word1word2相同。dp[i][j] = dp[i][j-1] + 1。意思是,如果我们能把word1的前i个字符转换为word2的前j-1个字符,那么我们只需要在其基础上对word1进行一步插入操作,就可以把word1的前i个字符转换为word2的前j个字符。
  • 情况二;通过删除一个字符,使得word1word2相同。dp[i][j] = dp[i-1][j] + 1。意思是,如果我们能把word1的前i-1个字符转换为word2的前j个字符,那么我们只需要在其基础上对word1进行一步删除操作,就可以把word1的前i个字符转换为word2的前j个字符。
  • 情况三:通过替换一个字符,使得word1word2相同。dp[i][j] = dp[i-1][j-1] + 1。意思是,如果我们能把word1的前i-1个字符转换为word2的前j-1个字符,那么我们只需要在其基础上对word1进行一步替换操作,把word1[i]换成word2[j],就可以把word1的前i个字符转换为word2的前j个字符。
  • 情况四:贪心情况。如果word1[i] = word2[j],则dp[i][j] = dp[i-1][j-1] + 1。意思是,如果word1的第i个字符和word2的第j个字符相同,则如果我们能把word1的前i-1个字符转换为word2的前j-1个字符,那么我们什么也不用干,就可以把word1的前i个字符转换为word2的前j个字符。

完整代码:

class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        dp = [[None for _ in range(len(word2)+1)] for _ in range(len(word1)+1)]
        for i in range(len(word1)+1):
            dp[i][0] = i
        for j in range(1, len(word2)+1):
            dp[0][j] = j
        for i in range(1, len(word1)+1):
            for j in range(1, len(word2)+1):
                if word1[i-1] == word2[j-1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
        return dp[len(word1)][len(word2)]

运行结果:

你可能感兴趣的:(LeetCode72:编辑距离)