力扣小白刷题之72题编辑距离

题目描述

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

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

思路和方法参考自:https://leetcode-cn.com/problems/edit-distance/solution/dong-tai-gui-hua-java-by-liweiwei1419/

思路

  • 动态规划告诉我们可以 自底向上 去思考一个问题,思路是:先想这个问题最开始是什么情况,这个问题是两个字符串都为空字符串的时候,然后逐个地,一个字符一个字符加上去,在加字符的过程中考虑【状态转移】
  • 由于要考虑空字符,因为状态空间要多设置一行,多设置一列。

方法:动态规划

第一步:状态定义

  • 定义 dp[i][j] 为 将word1的前 i 个字符转换成word2的前 j 个字符所使用的最少操作数
  • 说明:由于要考虑空字符串,状态的下标 i 、 j 和 字符的下标 i 、j 有一个位置的偏差。

第二步:状态转移方程

  • 状态转移方程通常是在做分类讨论,而分类讨论的过程,常常利用了这个问题的【最优子结构】
  • 如果 word1[i - 1] == word2[j - 1],dp[i][j] = dp[i - 1][j - 1];
  • 如果 word1[i - 1] != word2[j - 1],则将将word1的前 i 个字符转换成word2的前 j 个字符的最少操作数就等于下面三种情况的最小值:
    1. 替换: 考虑修改 word1[i - 1] 成为 word[j - 1],此时 dp[i][j] = dp[i - 1][j - 1] + 1;
    2. 删除: 考虑将 word1[i - 1] 删除,此时 dp[i][j] = dp[i - 1][j] + 1; 即 word1 前 i - 1 个字符到 word2前 j 个字符的最少操作数 + 1;
    3. 插入: 考虑将 word1 前 i 个字符的末尾添加一个字符 使得 word1[i] = word2[j - 1];此时考虑方案的时候,由于 word1[i] == word2[j - 1],状态转移时就不应该考虑 word2[j - 1],因此 word1 的前 i 个字符到 word2 的前 j - 1 个字符的最少操作数 + 1 就是此种方案的最少操作数。即 dp[i][j] = dp[i][j - 1] + 1;
    4. 在上面三种操作中取最小值 dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1;

注意: 必须得先判断两个字符串最后一个字符是否相等

第三步:base case

  • 从一个字符串变成空字符串,非空字符串的长度就是编辑距离
  • 以下代码其实就是在填表格的第 0 行、第 0 列:
for (int i = 1; i <= m; i++) {
	dp[i][0] = i;
}
for (int j = 1; j <= n; j++) {
 dp[j][0] = j;
}

第四步:思考输出

  • 返回dp[m][n];

第五步:思考状态压缩
看一下【状态转移方程】:

  • 如果末尾字符相等,就【抄】左上角单元格的值
  • 如果末尾字符不相等,就从【正上方】(删除)、【左边】(插入)、【左上角】(替换)三个单元格的值中选出最小的一个 + 1。
    在这里插入图片描述
    在这里插入图片描述
    因此,初看可以用【滚动数组】,更极端一点,用 2 * 2表格就可以完成操作。但是真正去做【状态压缩】的时候,由于初始化的原因,发现没有那么容易,在这里不做【状态压缩】。

代码

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值