95、动态规划-编辑距离

news2024/11/18 19:59:11

递归暴力解法

递归方法的基本思想是考虑最后一个字符的操作,然后根据这些操作递归处理子问题。

递归函数定义:定义一个递归函数 minDistance(i, j),表示将 word1 的前 i 个字符转换成 word2 的前 j 个字符所需的最小操作数。

递归终止条件

  • 如果 i == 0,意味着 word1 为空,此时将 word1 转换成 word2 的前 j 个字符就需要 j 次插入操作。
  • 如果 j == 0,意味着 word2 为空,此时将 word1 的前 i 个字符转换成空字符串需要 i 次删除操作。

递归转移方程

  • 如果 word1[i-1] == word2[j-1],则当前两个字符相等,不需要操作,所以 minDistance(i, j) = minDistance(i-1, j-1)
  • 如果不相等,则可以进行插入、删除或替换操作,转移方程为:
    • 插入:minDistance(i, j) = minDistance(i, j-1) + 1
    • 删除:minDistance(i, j) = minDistance(i-1, j) + 1
    • 替换:minDistance(i, j) = minDistance(i-1, j-1) + 1
  • 取三者的最小值。

代码如下:

public class Solution {
    // 主方法,用于外部调用,传入两个字符串
    public int minDistance(String word1, String word2) {
        // 调用递归助手函数,初始化i和j为字符串的长度,从字符串尾部开始比较
        return minDistanceHelper(word1, word2, word1.length(), word2.length());
    }

    // 递归助手函数,用于计算两个字符串的最小编辑距离
    private int minDistanceHelper(String word1, String word2, int m, int n) {
        // 如果第一个字符串为空,则转换的代价是第二个字符串的长度(即插入n次)
        if (m == 0) return n;
        // 如果第二个字符串为空,则转换的代价是第一个字符串的长度(即删除m次)
        if (n == 0) return m;

        // 如果两个字符串的当前字符相等,则不需要操作,递归考虑前一个字符
        if (word1.charAt(m - 1) == word2.charAt(n - 1)) {
            return minDistanceHelper(word1, word2, m - 1, n - 1);
        }

        // 计算插入操作的代价:将word2的第n个字符插入到word1的末尾,然后继续处理剩余的字符串
        int insert = minDistanceHelper(word1, word2, m, n - 1) + 1;
        // 计算删除操作的代价:删除word1的第m个字符,然后继续处理剩余的字符串
        int delete = minDistanceHelper(word1, word2, m - 1, n) + 1;
        // 计算替换操作的代价:将word1的第m个字符替换为word2的第n个字符,然后继续处理剩余的字符串
        int replace = minDistanceHelper(word1, word2, m - 1, n - 1) + 1;

        // 返回三种操作中的最小值,即为到当前位置为止的最小编辑距离
        return Math.min(Math.min(insert, delete), replace);
    }
}

但是重复计算效率很慢,改成动态规划:

动态规划方法

动态规划方法的核心思想是使用一个二维数组 dp 来存储中间结果,其中 dp[i][j] 表示将 word1 的前 i 个字符转换成 word2 的前 j 个字符所需的最小操作数。通过填充这个数组,我们可以逐步构建出从一个空字符串到完整 word2,再从完整 word1word2 的转换路径。

初始化:
  • dp[0][j]:将空字符串转换为 word2 的前 j 个字符,需要 j 次插入操作。
  • dp[i][0]:将 word1 的前 i 个字符转换为空字符串,需要 i 次删除操作。
状态转移方程:
  • 如果 word1[i-1] == word2[j-1],则 dp[i][j] = dp[i-1][j-1],因为最后一个字符已经匹配,不需要额外操作。
  • 如果 word1[i-1] != word2[j-1],则可以从以下三个可能的操作中选择最小成本的:
    • 插入:dp[i][j] = dp[i][j-1] + 1
    • 删除:dp[i][j] = dp[i-1][j] + 1
    • 替换:dp[i][j] = dp[i-1][j-1] + 1

代码如下:

public class Solution {
    public int minDistance(String word1, String word2) {
        int m = word1.length();
        int n = word2.length();
        int[][] dp = new int[m + 1][n + 1];

        // 初始化dp数组
        for (int i = 0; i <= m; i++) {
            dp[i][0] = i;  // 从word1的i字符变为空字符串
        }
        for (int j = 0; j <= n; j++) {
            dp[0][j] = j;  // 从空字符串变为word2的j字符
        }

        // 填充dp数组
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                    dp[i][j] = dp[i-1][j-1];
                } else {
                    dp[i][j] = Math.min(Math.min(dp[i-1][j] + 1, dp[i][j-1] + 1), dp[i-1][j-1] + 1);
                }
            }
        }
        return dp[m][n];
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1657710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

命运交织的节点:分布式事务最终一致性的心跳共鸣纪实

关注微信公众号 “程序员小胖” 每日技术干货&#xff0c;第一时间送达&#xff01; 引言 在当今云计算和微服务架构大行其道的时代&#xff0c;分布式系统成为了构建高可用、高性能应用的基石。然而&#xff0c;随着系统规模的扩张&#xff0c;数据的一致性问题如同幽灵般萦…

Linux字符设备驱动(一) - 框架

字符设备是Linux三大设备之一(另外两种是块设备&#xff0c;网络设备)&#xff0c;字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备&#xff0c;常见的字符设备包括鼠标、键盘、显示器、串口等等&#xff0c;当我们执行ls -l /dev的时候&#xff0c;就能看到大量…

C++容器之vector类

目录 1.vector的介绍及使用1.1vector的介绍1.2vector的使用1.2.1 vector的定义1.2.2 vector iterator 的使用1.2.3 vector 空间增长问题1.2.4 vector 增删查改1.2.5vector 迭代器失效问题1.2.6 vector 在OJ中的使用。 2.vector深度剖析及模拟实现2.1 std::vector的核心框架接口…

Kotlin基础知识总结(三万字超详细)

1、条件语句 &#xff08;1&#xff09;if条件 if条件表达式&#xff0c;每一个分支最后一条语句就是该分支的返回值。适用于每个分支返回值类型一致这种情况。 fun getDegree(score: Int): String{val result: String if(score 100){"非常优秀"}else if(score …

【2024全国青少年信息素养大赛初赛时间以及模拟题】

2024全国青少年信息素养大赛时间已经出来了 目录 全国青少年信息素养大赛智能算法挑战赛初中模拟卷 全国青少年信息素养大赛智能算法挑战赛初中模拟卷 1、比赛时间和考试内容&#xff1a; 算法创意实践挑战赛初中组于5月19日举行&#xff0c;检录时间为10:30-11:00&#xf…

OS复习笔记ch5-3

引言 上一节我们学习了关于信号量机制的一些内容&#xff0c;包括信号量的含义&#xff0c;对应的PV操作等。 如图所示&#xff0c;上一节主要是针对信号量的互斥&#xff0c;其实信号量机制还可以做很多事情&#xff0c;比如实现进程同步和前驱关系&#xff0c;这一节我们先复…

leetcode每日一题第七十二天

class Solution { public:TreeNode* searchBST(TreeNode* root, int val) {if(!root) return root;if(root->val val) return root;else if(root->val > val) return searchBST(root->left,val);else return searchBST(root->right,val);} };

新能源汽车动力电池热管理方案直冷方案原理简介

前言 随着新能源汽车的快速发展&#xff0c;动力电池作为其核心部件之一&#xff0c;对于其性能和寿命具有重要影响。动力电池在工作过程中会产生大量的热量&#xff0c;如果不能有效地进行热管理&#xff0c;将会导致电池温度升高、性能下降甚至损坏。因此&#xff0c;热管理…

C语言【文件操作 2】

文章目录 前言顺序读写函数的介绍fputc && fgetcfputcfgetc fputs && fgetsfputsfgets fprintf && fscanffprintffscanf fwrite && freadfwritefread 文件的随机读写fseek函数偏移量ftell函数rewind函数 文件的结束判断被错误使用的feof 结语 …

哈希题目总结

以下列举了可以用哈希方法&#xff08;包括但不限于用HashMap和HashSet&#xff09;的题目&#xff0c;实质上是把东西丢给这些数据结构去维护。请注意有些题目中用哈希是最优解&#xff0c;有些题目中不是最优解&#xff0c;可以自行探索其时间复杂度和空间复杂度的区别&#…

【Java】还不会数组?一文万字全搞定

前言&#xff1a;前面两章我们详细讲解了Java基本程序设计结构中的基本知识&#xff0c;&#xff0c;包括&#xff1a;一个简单的Java应用&#xff0c;注释&#xff0c;数据类型&#xff0c;变量与常量&#xff0c;运算符&#xff0c;字符串&#xff0c;输入输出&#xff0c;控…

探索精酿啤酒:从经典到创新

Fendi club啤酒一直以来都以其卓着的品质和与众不同的口感深受消费者喜爱。而随着时代的变迁和消费者口味的不断变化&#xff0c;Fendi club啤酒也在不断地探索和创新&#xff0c;以满足市场的多样化需求。 在经典的口感和风味基础上&#xff0c;Fendi club啤酒不断地尝试新的原…

多线程学习D10 收尾了应该

线程安全集合类概述 重点介绍java.util.concurrent.* 下的线程安全集合类&#xff0c;可以发现它们有规律&#xff0c;里面包含三类关键词&#xff1a;Blocking、CopyOnWrite、Concurrent Blocking 大部分实现基于锁&#xff0c;并提供用来阻塞的方法 CopyOnWrite 之类容器修改…

探讨关于AutoPSA里CII算法的结构荷载

UKP3D,AutoPDMS导出应力计算文件至管道应力分析软件分析&#xff0c;如下图AutoPSA.用户咨询如图 1.如果计算时考虑水重&#xff0c;把工况中的w改为ww&#xff1b; 2.CAD表格中结构荷载不是单纯的1.5倍&#xff0c;是参照仿GLIF的算法&#xff0c;计算了水重的&#xff08;根…

如何进行资产梳理

前言 为什么要进行资产梳理&#xff1f; 资产梳理方式一: 一、安全防护设备资产 二、对外开放服务项目资产 三、项目外包业务流程资产 资产梳理方式二: 一、业务资源梳理 二、设备资产梳理 三、第三方的服务信息梳理 风险梳理 风险有哪些&#xff1f; 一,账号权限风…

在windows下使用VS Code、CMake、Make进行代码编译

软件环境 Windows11VS CodeNoneCMake3.26.4-windows-x86_64MinGWNone 电脑系统配置 安装MinGW将MinGW安装文件夹中bin文件夹下的mingw32-make.exe复制并重命名为make.exe在文件夹中添加系统路径&#xff0c;具体位置为 系统->系统信息->高级系统设置->高级->环境…

Core_Air724UG学习

产品描述 Core_Air724UG核心板是基于Air724UG cat1模板制作的开发实验板。 该模块支持Lua二次开发或AT指令&#xff0c;方便开发者根据自己的需求灵活选择。 Core_Air724UG核心板专注于小型化&#xff0c;PCB尺寸4246mm&#xff0c;有12x22哥标准2.54mm排针管脚&#xff0c;其…

Android MediaCodec 简明教程(七):使用 MediaCodec 解码到 OES 纹理上

系列文章目录 Android MediaCodec 简明教程&#xff08;一&#xff09;&#xff1a;使用 MediaCodecList 查询 Codec 信息&#xff0c;并创建 MediaCodec 编解码器Android MediaCodec 简明教程&#xff08;二&#xff09;&#xff1a;使用 MediaCodecInfo.CodecCapabilities 查…

安装oh-my-zsh(命令行工具)

文章目录 一、安装zsh、git、wget二、安装运行脚本1、curl/wget下载2、手动下载 三、切换主题1、编辑配置文件2、切换主题 四、安装插件1、zsh-syntax-highlighting&#xff08;高亮语法错误&#xff09;2、zsh-autosuggestions&#xff08;自动补全&#xff09; 五、更多优化配…

FFmpeg常用命令详解与实战指南

下载地址&#xff1a;Releases BtbN/FFmpeg-Builds (github.com) 1. 获取视频信息 使用FFmpeg获取视频信息是最基本的操作之一。你可以使用-i选项指定输入文件&#xff0c;然后使用FFmpeg内置的分析器来获取视频的各种信息&#xff0c;包括视频编解码器、音频编解码器、分辨…