当前位置: 首页 > java >正文

力扣72:编辑距离

力扣72:编辑距离

  • 题目
  • 思路
  • 代码

题目

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

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

示例 1:
输入:word1 = “horse”, word2 = “ros”
输出:3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)

思路

首先我们来解析一下这三种操作本质上是干什么,假设我们有两个字符串A和B。

  1. 插入一个字符
    插入一个字符我们可以将其分为对字符串A进行插入和对字符串B进行插入,我们可以发现对A进行插入不就是对B进行删除吗,对B进行插入就是对A进行删除。例如A是“thing”,B是“hing“,我们既可以对A进行删除也可以对B进行插入,这两种操作都可以得到答案所有他们俩是等价的。
  2. 删除一个字符
    删除一个字符一样可以分为对A进行删除和对B进行删除,根据上面的结论对A删除就是对B插入,对B删除就是对A进行插入。
  3. 替换一个字符
    替换一个字符同样是分为对A进行替换和对B进行替换,这个两个操作就不用多提了同样是等价的,例如A是"thing",B是"ching”。我们可以将A的t换成c也可以将B的c换成t。

所以上面的三种操作最后我们可以等价于下面三种操作

  1. 对A插入一个字符
  2. 对B插入一个字符
  3. 对A替换一个字符

那么在得到这样的结论之后呢?我们是不是可以把总的问题划分成不同的子问题例如测试用例里的A是“horse”,B是“ros”。我们根据上面的操作发现这个测试用例的答案不就是A是horse,B是ro的答案+1吗,那么这个问题是不是还能继续简化,A是horseB是r,再到A是horseB是空串,再到A是horsB是空串,直到最后A是空串B也是空串。A是空串B是空串的编译距离很好求把那么我们不就可以再从最简化的往前一步一步的求得最初的了吗?
而我们进行的操作又只有上面三种,所以我们想要求得一个字符串到另外一个字符串的编辑距离只要知道在对A进行插入一个字符前的编辑距离,对B进行插入一个字符前的编辑距离,对A进行替换一个字符的编辑距离即可。题目又说是最小的编辑距离所以只要求得这三个距离的最小值当作当前值即可。
这种划分子问题然后从子问题一步一步推导的思想不就是动态规划吗,所以我们定义一个二维数组dp,同时定义i是字符串A的下标,j是字符串B的下标。那么dp[i][j]的意思就是A字符串的前i个字母到B字符串的前j个字母的编辑距离了。通过上面的分析我们可以得到dp[i][j]的状态推导函数是
dp[i][j]=min(dp[i−1][j]+1,min(dp[i][j−1]+1,dp[i−1][j−1]))dp[i][j] = min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1])) dp[i][j]=min(dp[i1][j]+1,min(dp[i][j1]+1,dp[i1][j1]))
首先是取这三个值中的最小值这肯定没问题,这三个值分别都是什么意思呢?
dp[i-1][j]对应着第一个操作:对字符串A插入一个字符。
dp[i][j-1]对应着第二个操作:对字符串B插入一个字符。
dp[i-1][j-1]对应着第三个操作:对字符串A替换一个字符。
前两个比较好理解,我们只需要得到操作之前的编辑距离再+1就是操作之后的编辑距离,第三个需要我们提前判断前一个位置的AB字符串字符是不是相同的如果不相同就需要对dp[i-1][j-1]进行++。

代码

class Solution {
public:int minDistance(string word1, string word2) {int n = word1.length();int m = word2.length();// 如果有一个字符串为空串if (n == 0 || m == 0) {return n == 0 ? m : n;}// 动态规划,二维数组,dp[i][j]是word1的第i个位置到word2第j个位置的编译距离vector<vector<int>> dp(n + 1, vector<int>(m + 1));//边界,空串到非空串的编辑距离就是非空串的长度for (int i = 0; i < n + 1; i++) {dp[i][0] = i;}for (int j = 0; j < m + 1; j++) {dp[0][j] = j;}for (int i = 1; i < n + 1; i++) {for (int j = 1; j < m + 1; j++) {//判断前一个字符是否相同if (word1[i - 1] != word2[j - 1]) {dp[i - 1][j - 1] += 1;}//状态转移方程dp[i][j] = min(dp[i - 1][j] + 1,min(dp[i][j - 1] + 1, dp[i - 1][j - 1]));}}return dp[n][m];}
};
http://www.xdnf.cn/news/19738.html

相关文章:

  • windows docker(二) 启动存在的容器
  • 5招教你看透PHP开发框架的生态系统够不够“牛”?
  • 推荐一个论文阅读工具ivySCI
  • latex怎么写脚注:标共一声明,标通讯作者
  • 使用 Avidemux 去除视频的重复帧
  • 从实操到原理:一文搞懂 Docker、Tomcat 与 k8s 的关系(附踩坑指南 + 段子解疑)
  • 血缘元数据采集开放标准:OpenLineage Guides 在 Spark 中使用 OpenLineage
  • SpringBoot3中使用Caffeine缓存组件
  • 模版进阶及分离编译问题
  • ansible判断
  • 科学研究系统性思维的方法体系:数据分析模板
  • C语言:归并排序和计数排序
  • OCR识别在媒资管理系统的应用场景剖析与选择
  • 基于ZooKeeper实现分布式锁(Spring Boot接入)及与Kafka实现的对比分析
  • Pod自动重启问题排查:JDK 17 EA版本G1GC Bug导致的应用崩溃
  • Element Plus 表格表单校验功能详解
  • 【Web前端】JS+DOM来实现乌龟追兔子小游戏
  • 轻型载货汽车变速器设计cad+设计说明书
  • 【序列晋升】25 Spring Cloud Open Service Broker 如何为云原生「服务市集」架桥铺路?
  • 分布式光纤传感选型 3 问:你的场景该选 DTS、DAS 还是 BOTDA?
  • 2017考研数学(二)真题
  • vue2滑块验证
  • Coze源码分析-工作空间-资源查询-后端源码
  • 解读“2025年OWASP大模型十大安全风险”与相关攻击案例
  • 《驾驭云原生复杂性:隐性Bug的全链路防御体系构建》
  • Valkey vs Redis详解
  • thinkphp5配置hg/apidoc接口文档
  • 嵌入式硬件 - 51单片机1
  • 驾驭金钱:每一次花钱,都是一次选择
  • Linux《进程信号(上)》