栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Leetcode每日一题——72. 编辑距离。动态规划

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Leetcode每日一题——72. 编辑距离。动态规划

题目链接:

力扣

题目描述:

给你两个单词 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 由小写英文字母组成

解题思路:

编辑距离可以理解为为了使2个序列一模一样,对2个序列的修改(包括增删改)次数之和

        那么题意就是要我们求最小编辑距离了

        遇到2个字符串的比较问题,用动态规划的话一般都是设置2个维度的dp数组分别表示2个字符串的状态。所以这里可以设置dp[i][j]表示分别以word1[i-1]、word2[j-1]结尾的字符串的最小编辑距离

        dp四部曲:

        确定dp数组:dp[i][j]表示分别以word1[i-1]、word[j-1]结尾的字符串的最小编辑距离

        确定递推关系:对于word1[i-1]、word[j-1]有2种状态:

            如果相等,那么dp[i][j]=dp[i-1][j-1],即编辑距离与上一对字符的相同。

            如果不等,又分为3种情况,增删改。但是增和删是等效的,可归为一种情况,例如对于'ab','a',增加b和删除b都可以使2者相同,且2种情况的编辑距离都为1,所以从结果来说这2种操作是等效的;所以实际上不等就2种情况:

                删的话可以选择删掉word1[i-1],那么此时dp[i][j]=dp[i-1][j]+1,即在使分别以word[i-2],word[j-1]结尾的字符串相等的情况下删掉word[i-1],使分别以word[i-1],word[j-1]结尾的字符串相等(此时word[i-1]相当于空字符串);如果选择删掉word2[j-1]的话dp[i][j]=dp[i][j-1]+1。

                改的话就是在在使分别以word[i-2],word[j-2]结尾的字符串相等的情况下改word1[i-1]或者word2[j-1]使分别以word[i-1],word[j-1]结尾的字符串相等,那么dp[i][j]=dp[i-1][j-1]+1了

            由于取最小编辑距离,所以等的情况dp[i][j]=dp[i-1][j-1],不等的时候dp[i][j]=min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1])+1

        初始化dp数组:由递推公式可知,dp[i][j]有3个来源:左边、上方、左上方,所以初始化要初始化dp[0][x]和dp[x][0],根据定义,dp[0]表示跟下标为-1的字符串比较,这时就可认为是在跟空字串比较了,那么使别的字符串跟空字符串相同,最小编辑距离肯定就是把字符串内容全删了,也就是len(string)了。除了dp[0][x]和dp[x][0],其他都初始化为0

        确定遍历顺序:dp[i][j]有3个来源:左边、上方、左上方。所以遍历顺序应该是从上到下从左到右

代码实现如下:

class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        if len(word1) == 0: return len(word2)
        if len(word2) == 0: return len(word1)
        dp = [[0] * (len(word2) + 1) for i in range(len(word1) + 1)]#行是1,列是2
        for i in range(len(dp)): dp[i][0] = i
        for i in range(len(dp[0])): dp[0][i] = i
        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[-1][-1]

考虑到dp[i][j]有3个来源:左边、上方、左上方。所以可以用二维滚动数组降低空间复杂度,代码如下:

class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        if len(word1) == 0: return len(word2)
        if len(word2) == 0: return len(word1)
        dp = [[0] * (len(word2) + 1) for i in range(2)]#行是1,列是2
        for i in range(len(dp)): dp[i][0] = i
        for i in range(len(dp[0])): dp[0][i] = i
        for i in range(1, len(word1) + 1):
            for j in range(1, len(word2) + 1):
                if word1[i - 1] == word2[j - 1]:
                    dp[1][j] = dp[0][j - 1]
                else:
                    dp[1][j] = min(dp[0][j], dp[1][j - 1], dp[0][j - 1]) + 1
            dp[0] = [k for k in dp[1]]
            dp[1][0] += 1#更新word1[i]与word2[-1](空字符串)的比较结果
        return dp[-1][-1]

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/951628.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号