LeetCode 72.编辑距离

news/2025/2/9 3:30:03 标签: leetcode, 算法, 职场和发展

要解决LeetCode 72题“编辑距离”问题,我们可以使用动态规划的方法。以下是详细的C++解题思路和实现过程:

解题思路

  1. 问题分析
    编辑距离问题要求将字符串 word1 转换为 word2 所需的最少操作次数,允许的操作包括插入、删除和替换字符。动态规划适用于这类具有重叠子问题和最优子结构的问题。

  2. 状态定义
    定义二维数组 dp[i][j],表示将 word1 的前 i 个字符转换为 word2 的前 j 个字符所需的最小操作次数。

  3. 状态转移方程

    • 字符匹配:若 word1[i-1] == word2[j-1],则无需操作,直接继承前一步的结果:
      dp[i][j] = dp[i-1][j-1]
    • 字符不匹配:需从插入、删除、替换中选择操作次数最少的一种:
      dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
  4. 初始化

    • dp[i][0] = i:删除 i 个字符使 word1 变空。
    • dp[0][j] = j:插入 j 个字符使空字符串变为 word2 的前 j 个字符。
  5. 填充顺序
    按顺序遍历 i1mj1n,确保子问题已解决。

三种操作的具体解释

你提到的三种操作对应的状态转移方程理解是正确的,但可能还不够直观。让我们通过具体场景表格推导来彻底理解这些操作的数学含义,以及为什么最终要取这三个值的最小值。


1、操作的本质与状态转移关系

假设我们有两个字符串:

  • word1 = "abc"(长度 m=3)
  • word2 = "abd"(长度 n=3)

建立二维DP表 dp[4][4](索引从0到3):

i\j0 (空)1 (a)2 (b)3 (d)
00123
1 (a)1???
2 (b)2???
3 ©3???

现在我们要计算 dp[3][3](即 word1[0..2]转成word2[0..2])。


场景1:插入操作(对应 dp[i][j-1] + 1
  • 当前字符word1[2] = 'c' vs word2[2] = 'd'
  • 插入操作:在word1末尾插入d,此时word1变为"abcd"
    • 此时word1[3]d已经匹配word2[2]d
    • 剩下的问题转化为将word1[0..2](即"abc")转为word2[0..1](即"ab"
    • 这个子问题的解是 dp[3][2]
    • 总操作次数 = dp[3][2] + 1

场景2:删除操作(对应 dp[i-1][j] + 1
  • 删除操作:删除word1[2]c,此时word1变为"ab"
    • 剩下的问题是将"ab"转为"abd"
    • 这个子问题的解是 dp[2][3]
    • 总操作次数 = dp[2][3] + 1

场景3:替换操作(对应 dp[i-1][j-1] + 1
  • 替换操作:将word1[2]c替换为d
    • 此时word1变为"abd"
    • 剩下的问题是将"ab"转为"ab"
    • 这个子问题的解是 dp[2][2]
    • 总操作次数 = dp[2][2] + 1

2、具体数值推导

假设我们已经计算出前面的值:

i\j0123
00123
11012
22101
3321?

现在计算 dp[3][3]

  1. 插入dp[3][2] + 1 = 1 + 1 = 2
  2. 删除dp[2][3] + 1 = 1 + 1 = 2
  3. 替换dp[2][2] + 1 = 0 + 1 = 1

最终取最小值 1,即通过替换操作只需1步。


3、为什么取三种操作的最小值?

这三种操作涵盖了所有可能的编辑方式:

  1. 插入:适用于word1word2短的情况(需要补字符)
  2. 删除:适用于word1word2长的情况(需要删冗余字符)
  3. 替换:适用于字符不匹配但长度相同的情况

通过动态规划,我们始终选择历史最优解(已计算的子问题最优解)加上当前操作的最小代价。


4、边界条件的深层理解
  • dp[i][0] = i:将长度为i的字符串变为空串,只能删除i次
  • dp[0][j] = j:将空串变为长度为j的字符串,只能插入j次

例如:

  • word1 = "abc", word2 = "" → 需要删除3次
  • word1 = "", word2 = "abc" → 需要插入3次

C++代码实现

#include <vector>
#include <algorithm> // 用于min函数

using namespace std;

int minDistance(string word1, string word2) {
    int m = word1.size(), n = word2.size();
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
    
    // 初始化边界条件
    for (int i = 0; i <= m; ++i) dp[i][0] = i;
    for (int j = 0; j <= n; ++j) dp[0][j] = j;
    
    // 填充dp数组
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            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[m][n];
}

代码解析

  • 时间复杂度:O(m*n),需要遍历二维数组的所有元素。
  • 空间复杂度:O(m*n),用于存储动态规划表。
  • 关键点
    • 通过比较当前字符是否相等决定操作方式。
    • 使用 min({a, b, c}) 取三者最小值(C++11特性)。
    • 边界条件初始化正确处理空字符串的情况。

示例验证

  • 输入word1 = "horse", word2 = "ros"
    输出:3
    解释:替换 h→r,删除 r,删除 e,共3步。

  • 输入word1 = "intention", word2 = "execution"
    输出:5
    解释:通过替换、删除等操作匹配字符串。


http://www.niftyadmin.cn/n/5845490.html

相关文章

零基础学习书生.浦语大模型--基础岛

第二关:玩转书生[多模态对话]和[AI搜索]产品 任务一&#xff1a;使用MindSearch 任务二&#xff1a;尝试使用书生.浦语 尝试让其写一段Self-Attention网络模块代码 import torch import torch.nn as nn import torch.nn.functional as Fclass SelfAttention(nn.Module):def _…

Explain 是 SQL 查询优化中非常重要的工具,它用于分析 SQL 查询的执行计划

Explain 是 SQL 查询优化中非常重要的工具&#xff0c;它用于分析 SQL 查询的执行计划https://mp.weixin.qq.com/s/QKra-Sp5JoaEPSCqfffOtA

Spring Cloud 01 - 微服务概述

微服务概述 文章目录 微服务概述一&#xff1a;分布式和微服务1、什么是微服务&#xff1f;2&#xff1a;什么是分布式3、联系与区别是什么&#xff1f; 2&#xff1a;最终技术搭配方案 一&#xff1a;分布式和微服务 1、什么是微服务&#xff1f; 微服务架构是团队面对互联网…

centos虚拟机迁移没有ip的问题

故事背景&#xff0c;我们的centos虚拟机本来是好好的&#xff0c;但是拷贝到其他电脑上就不能分配ip&#xff0c;我个人觉得这个vmware他们软件应该搞定这个啊&#xff0c;因为这个问题是每次都会出现的。 网络选桥接 网络启动失败 service network restart Restarting netw…

数据库基础练习4(有关索引,视图完整解答)

建立需要的表 学生表 mysql> create table studnet(sno int primary key auto_increment,sname varchar(30) not null unique,ssex varchar(2) check (ssex男 or ssex女) not null ,sage int not null,sdept varchar(10) default 计算机 not null); Query OK, 0 rows affe…

3. 【.NET Aspire 从入门到实战】--理论入门与环境搭建--环境搭建

构建现代云原生应用程序时&#xff0c;开发环境的搭建至关重要。NET Aspire 作为一款专为云原生应用设计的开发框架&#xff0c;提供了一整套工具、模板和集成包&#xff0c;旨在简化分布式系统的构建和管理。开始项目初始化之前&#xff0c;确保开发环境的正确配置是成功的第一…

青少年编程与数学 02-008 Pyhon语言编程基础 22课题、类的定义和使用

青少年编程与数学 02-008 Pyhon语言编程基础 22课题、类的定义和使用 一、类类的定义和使用示例 二、定义1. 类定义语法2. 属性和方法3. 构造器和初始化4. 实例化5. 类变量和实例变量6. 类方法和静态方法7. 继承8. 多态总结 三、使用1. 创建类的实例2. 访问属性3. 调用方法4. 修…

UV - Python 包管理

文章目录 创建 uv 项目已有项目已有uv项目 创建 uv 项目 # 创建项目 uv init m3 # 创建环境 cd m3 uv venv --python 3.11 # 激活环境 source .venv/bin/activate # 添加库 uv add flask 如果创建项目后&#xff0c;给库取别的名字&#xff0c;add 的时候&#xff0c;会…