代码随想录算法训练营第四十八天| 115.不同的子序列、583. 两个字符串的删除操作、 72. 编辑距离

115.不同的子序列

在这里插入图片描述

题目链接:115.不同的子序列
文档讲解:代码随想录
状态:不会

思路:
dp[i][j] 表示在 s 的前 j 个字符中,t 的前 i 个字符作为子序列出现的次数。

匹配的情况:
1.当 s[j-1] 与 t[i-1] 匹配时,说明我们可以用 s[j-1] 来匹配 t[i-1],这种情况下,在 s 的前 j-1 个字符中找到的所有 t 的前 i-1 个字符作为子序列的组合数(dp[i-1][j-1])都可以作为当前组合的一部分。例如: t:ba(g) s:bag(g) ,当t[2]=s[3]时,如果使用s[3]的话,dp[2][3]可以由dp[1][2]得到,也就是t:ba(g)在s:bag(g)中的出现次数可以由ba在bag出现的次数推导过来,因为t和s都加上一个相同的g。这是推导dp[i][j]的可能情况之一。
2.此外,即使不使用 s[j-1] 也可以完成匹配,这种情况下,只需要在 s 的前 j-1 个字符中找到 t 的前 i 个字符作为子序列的组合数(dp[i][j-1])。例如:t:ba(g) s:bag(g) ,如果不使用s[3],就是看 t:ba(g) 和 s:ba(g) ,这种情况 dp[2][3] 可以由dp[2][2]得到,也就是t:ba(g)在s:bag(g)中的出现次数可以由t:bag在s:bag出现的次数推导过来。这也是推导dp[i][j]的一种情况。
所以: s[j-1] 与 t[i-1] 匹配时,dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];

不匹配的情况:
当 s[j-1] 与 t[i-1] 不匹配时,说明我们不能用 s[j-1] 来匹配 t[i-1]。这种情况下,我们只能在 s 的前 j-1 个字符中找到 t 的前 i 个字符作为子序列的组合数(dp[i][j-1])。

初始状态
空字符串 t 是任何字符串 s 的子序列:因此,对于任何 j,dp[0][j] = 1。
空字符串 s 不能包含非空字符串 t:因此,对于任何 i > 0,dp[i][0] = 0。

题解:

    public int numDistinct(String s, String t) {
        // 将字符串转换为字符数组
        char[] sChars = s.toCharArray();
        char[] tChars = t.toCharArray();

        // 创建DP数组,dp[i][j]表示t的前i个字符在s的前j个字符中出现的次数
        int[][] dp = new int[t.length() + 1][s.length() + 1];

        // 初始化 dp[0][j] 为 1,因为空字符串t是任何字符串s的子序列
        for (int j = 0; j <= s.length(); j++) {
            dp[0][j] = 1;
        }

        // 填充DP数组
        for (int i = 1; i <= t.length(); i++) {
            for (int j = 1; j <= s.length(); j++) {
                if (tChars[i - 1] == sChars[j - 1]) {
                    // 如果当前字符匹配,可以选择匹配和不匹配两种情况
                    dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];
                } else {
                    // 如果当前字符不匹配,只能不匹配
                    dp[i][j] = dp[i][j - 1];
                }
            }
        }

        // 返回t的前t.length()个字符在s的前s.length()个字符中出现的次数
        return dp[t.length()][s.length()];
    }

583. 两个字符串的删除操作

在这里插入图片描述

题目链接:583. 两个字符串的删除操作
文档讲解:代码随想录
状态:做出来了有点磕绊

思路1:找到最大公共子序列数量,然后两个字符串分别减去它求和。

思路2:
dp[i][j]表示word1[0,i],word2[0,j],要使它们相同一共需要删去多少个字符。

当word1[i - 1] 与 word2[j - 1]相同的时候,显然dp[i][j] = dp[i - 1][j - 1];

当word1[i - 1] 与 word2[j - 1]不相同的时候:
情况一:删word1[i - 1],最少操作次数为dp[i - 1][j] + 1
情况二:删word2[j - 1],最少操作次数为dp[i][j - 1] + 1
情况三:同时删word1[i - 1]和word2[j - 1],操作的最少次数为dp[i - 1][j - 1] + 2
其中情况三隐含在情况一和二中,所以应该是情况1和2中应该取最小操作数,所以dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);

初始化:
dp[i][0]:word2为空字符串,以i-1为结尾的字符串word1要删除多少个元素,才能和word2相同呢,很明显dp[i][0] = i。
dp[0][j]的话同理

题解:

    public int minDistance(String word1, String word2) {
        // 将字符串转换为字符数组
        char[] w1 = word1.toCharArray();
        char[] w2 = word2.toCharArray();

        // 创建DP数组,dp[i][j]表示word1的前i个字符和word2的前j个字符的最长公共子序列长度
        int[][] dp = new int[word1.length() + 1][word2.length() + 1];

        // 填充DP数组
        for (int i = 1; i <= w1.length; i++) {
            for (int j = 1; j <= w2.length; j++) {
                if (w1[i - 1] == w2[j - 1]) {
                    // 如果当前字符匹配,LCS长度加1
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    // 如果当前字符不匹配,选择两个子问题中LCS最长的一个
                    dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
                }
            }
        }

        // 计算最少步骤:将两个字符串转换成它们的LCS需要的删除和插入操作数
        return word1.length() + word2.length() - 2 * dp[word1.length()][word2.length()];
    }

    public int minDistance2(String word1, String word2) {
        char[] w1 = word1.toCharArray();
        char[] w2 = word2.toCharArray();
        int m = word1.length(), n = word2.length();

        // 创建DP数组,dp[i][j]表示word1的前i个字符与word2的前j个字符变得相同所需删除的字符数
        int[][] dp = new int[m + 1][n + 1];

        // 初始化边界情况:将word1的前i个字符变为空字符串需要i步操作(全删除)
        for (int i = 1; i <= m; i++) {
            dp[i][0] = i;
        }

        // 初始化边界情况:将空字符串变成word2的前j个字符需要j步操作(全删除)
        for (int j = 1; j <= n; j++) {
            dp[0][j] = j;
        }

        // 填充DP数组
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (w1[i - 1] == w2[j - 1]) {
                    // 当前字符相等,不需要额外删除
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    // 当前字符不相等,选择删除word1[i - 1]或word2[j - 1]中的最小删除次数
                    dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
                }
            }
        }

        // 返回最终结果
        return dp[m][n];
    }

    //最少编辑距离思路
    public int minDistance3(String word1, String word2) {
        // 将字符串转换为字符数组
        char[] w1 = word1.toCharArray();
        char[] w2 = word2.toCharArray();
        int m = word1.length(), n = word2.length();

        // 创建DP数组,dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最少操作数
        int[][] dp = new int[m + 1][n + 1];

        // 初始化边界情况:word1的前i个字符转换为空字符串需要i步操作(全删除)
        for (int i = 1; i <= m; i++) {
            dp[i][0] = i;
        }

        // 初始化边界情况:空字符串转换为word2的前j个字符需要j步操作(全插入)
        for (int i = 1; i <= n; i++) {
            dp[0][i] = i;
        }

        // 填充DP数组
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (w1[i - 1] == w2[j - 1]) {
                    // 如果当前字符匹配,不需要额外操作
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    // 如果当前字符不匹配,选择三种操作中的最小值(插入、删除、替换)
                    dp[i][j] = Math.min(dp[i - 1][j] + 1, // 删除操作
                            Math.min(dp[i][j - 1] + 1, // 插入操作
                                    dp[i - 1][j - 1] + 1)); // 替换操作
                }
            }
        }

        // 返回将word1转换为word2所需的最少操作数
        return dp[m][n];
    }

72. 编辑距离

在这里插入图片描述

题目链接:72. 编辑距离
文档讲解:代码随想录
状态:不会

思路:
dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。

显然if (word1[i - 1] == word2[j - 1]) 那么说明不用任何编辑,dp[i][j] 就应该是 dp[i - 1][j - 1],即dp[i][j] = dp[i - 1][j - 1];

if (word1[i - 1] != word2[j - 1]),此时就需要编辑了,如何编辑呢?

操作一:word1删除一个元素,那么就是word1[0,i-1] 与 word2[0,j] 的最近编辑距离 再加上一个操作。
即 dp[i][j] = dp[i - 1][j] + 1;

操作二:word2插入一个元素,那么就是word1[0,i] 与 word2[0,j-1] 的最近编辑距离 再加上一个操作。

操作三:替换元素,word1替换word1[i - 1],使其与word2[j - 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 - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
}

初始化:
word1的前i个字符转换为空字符串需要i步操作(全删除)
空字符串转换为word2的前j个字符需要j步操作(全插入)

题解:

    public int minDistance(String word1, String word2) {
        // 将字符串转换为字符数组
        char[] w1 = word1.toCharArray();
        char[] w2 = word2.toCharArray();
        int m = word1.length(), n = word2.length();

        // 创建DP数组,dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最少操作数
        int[][] dp = new int[m + 1][n + 1];

        // 初始化边界情况:word1的前i个字符转换为空字符串需要i步操作(全删除)
        for (int i = 1; i <= m; i++) {
            dp[i][0] = i;
        }

        // 初始化边界情况:空字符串转换为word2的前j个字符需要j步操作(全插入)
        for (int i = 1; i <= n; i++) {
            dp[0][i] = i;
        }

        // 填充DP数组
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (w1[i - 1] == w2[j - 1]) {
                    // 如果当前字符匹配,不需要额外操作
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    // 如果当前字符不匹配,选择三种操作中的最小值(插入、删除、替换)
                    dp[i][j] = Math.min(dp[i - 1][j] + 1, // 删除操作
                            Math.min(dp[i][j - 1] + 1, // 插入操作
                                    dp[i - 1][j - 1] + 1)); // 替换操作
                }
            }
        }

        // 返回将word1转换为word2所需的最少操作数
        return dp[m][n];
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TextView 实现最后一行缩进指定距离

实现图上类似的效果。 指定最大行数为三行&#xff0c;最后一行缩进指定的距离。 如果行数小于三行&#xff0c;则不缩进。 同时文字两端对齐 代码里的 JustifyTextView &#xff08;两端对齐的 Textview &#xff09;详见 Android Textview 多行文本两端对齐_android tex…

混合贪心算法求解地铁线路调度

一、问题描述 城市轨道交通的繁荣发展&#xff0c;带来了车辆资源需求的日益增加。如何兼顾运营服务水平和运营成本&#xff0c;以最少的车底优质地完成运输任务成为一大严峻问题。本题在后续的描述中将由多辆动车和拖车组合而成的车组称为车底。在日常的运营组织中&#xff0…

单链表(C语言详细版)

1. 链表的概念及结构 概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 链表的结构跟火车车厢相似&#xff0c;淡季时车次的车厢会相应减少&#xff0c;旺季时车次的车厢会额外增加几节。…

elasticsearch SQL:在Elasticsearch中启用和使用SQL功能

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

苍穹外卖--导入分类模块功能代码

把各层代码拷贝到所需文件夹下&#xff0c; 进行编译 在运行 提交和推送仓库

C++:C++入门基础|命名空间|输入输出

欢迎来到HarperLee的学习笔记&#xff01; 博主主页传送门&#xff1a; HarperLee的博客主页! 想要一起进步的uu来后台哦&#xff01; 一、什么是C? 在此之前&#xff0c;我们所学习的C语言是一种结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&a…

【STM32】MDK的编译过程及文件类型全解

1.编译过程简介 编译&#xff1a;MDK软件使用的编译器是armcc和armasm&#xff0c; 它们根据每个c/c和汇编源文件编译成对应的以“.o”为后缀名的对象文件(Object Code&#xff0c;也称目标文件)&#xff0c; 其内容主要是从源文件编译得到的机器码&#xff0c;包含了代码、数据…

怎么压缩ppt?这几种压缩方法大家都在用!

怎么压缩ppt&#xff1f;当我们沉浸在PPT创作的海洋中&#xff0c;每一个精心的布局、每一个动人的动画&#xff0c;都仿佛是我们心血的结晶&#xff0c;然而&#xff0c;随着我们不断雕琢&#xff0c;PPT文件的大小也在悄然增长&#xff0c;如同一只隐形的巨兽&#xff0c;在不…

无线充电宝哪个牌子好?绿联、西圣、小米充电宝测评对比!

随着科技的不断进步和智能设备的普及&#xff0c;无线充电宝逐渐成为了现代人生活中的必需品。它们不仅方便了我们的日常充电需求&#xff0c;更减少了线缆的束缚&#xff0c;提高了使用的便捷性。在众多品牌中&#xff0c;绿联、西圣和小米作为市场上广受好评的无线充电宝品牌…

Windows下载、配置Java JDK开发环境的方法

本文介绍在Windows电脑中&#xff0c;安装JDK&#xff08;Java Development Kit&#xff09;&#xff0c;也就是Java开发工具包的详细方法。 JDK是Java软件开发的基础&#xff0c;由Oracle公司提供&#xff0c;用于构建在Java平台上运行的应用程序与组件等&#xff1b;其已经包…

【windows】安装抓包工具Burp Suite 2024激活汉化

前言 在项目即将上线阶段&#xff0c;迈入生产环境之际&#xff0c;确保其安全性成为我们不可忽视的首要任务。为筑起一道坚不可摧的安全防线&#xff0c;我们借助业界公认的网络安全利器——Burp Suite&#xff0c;我们将展开一场全面的安全测试&#xff0c;旨在探查并消除任…

旗晟机器人AI智能算法有哪些?

在当今迅猛发展的工业4.0时代&#xff0c;智能制造和自动化运维已然成为工业发展至关重要的核心驱动力。伴随技术的持续进步&#xff0c;工业场景中的运维巡检已不再单纯地依赖于传统的人工运维方式&#xff0c;而是愈发多地融入了智能化的元素&#xff0c;其中智能巡检运维系统…

数据库MySQL---基础篇

存储和管理数据的仓库 MySQL概述 数据库相关概念 数据库&#xff08;DataBase&#xff09;---数据存储的仓库&#xff0c;数据是有组织的进行存储 数据库管理系统&#xff08;DBMS&#xff09;-----操纵和管理数据库的大型软件 SQL----操作关系型数据库的编程语言&#xff…

文华财经盘立方多空变色波段趋势线指标公式源码

文华财经盘立方多空变色波段趋势线指标公式源码&#xff1a; N1:20; N2:ROUND(N1/2,1); N3:ROUND(SQRT(N1),1); N4:2*EMA2(C,N2)-EMA2(C,N1); 尊重市场:EMA2(N4,N3),COLORRED,LINETHICK2; 尊重市场1:IF(尊重市场<REF(尊重市场,1), 尊重市场,NULL),COLORGREEN,LINETHIC…

gitlab-runner安装部署CI/CD

手动安装 卸载旧版&#xff1a; gitlab-runner --version gitlab-runner stop yum remove gitlab-runner下载gitlab对应版本的runner # https://docs.gitlab.com/runner/install/bleeding-edge.html#download-any-other-tagged-releasecurl -L --output /usr/bin/gitlab-run…

打开IDEA,程序员思考的永远只有两件事!!!

微信公众号&#xff1a;牛奶 Yoka 的小屋 有任何问题。欢迎来撩~ 最近更新&#xff1a;2024/07/09 [大家好&#xff0c;我是牛奶。] 当年面试时背了很多八股文&#xff0c;但在日渐重复的机械工作中&#xff08;产品业务开发&#xff09;&#xff0c;计算机网络、操作系统、算…

leetcode:LCR 018. 验证回文串(python3解法)

难度&#xff1a;简单 给定一个字符串 s &#xff0c;验证 s 是否是 回文串 &#xff0c;只考虑字母和数字字符&#xff0c;可以忽略字母的大小写。 本题中&#xff0c;将空字符串定义为有效的 回文串 。 示例 1: 输入: s "A man, a plan, a canal: Panama" 输出: t…

编辑器 goland 和 visual studio code

goland 编辑器做的真是太好了&#xff0c;面向 go 代码的定制设计&#xff0c;但它是收费软件&#xff0c;价格还贵的超出了自己的经济能力范围。有时候想打几行代码&#xff0c;却没有趁手的兵器&#xff0c;真是难受。但求助免费破解版吧&#xff0c;又需要关注公众号&#x…

Lab1 论文 MapReduce

目录 &#x1f339;前言 &#x1f985;2 Programming Model &#x1f33c;2.1 Example &#x1f33c;2.2 Types &#x1f33c;2.3 More Examples &#x1f985;3 Implementation(实现) &#x1f33c;3.1 ~ 3.3 &#x1f33c;3.4 ~ 3.6 &#x1f985;4 Refinemen…

Java-Redis-Clickhouse-Jenkins-MybatisPlus-Zookeeper-vscode-Docker-jdbc-xxljob

文章目录 Clickhouse基础实操windows docker desktop 下载clickhousespringboot项目配置clickhouse Redis谈下你对Redis的了解&#xff1f;Redis一般都有哪些使用的场景&#xff1f;Redis有哪些常见的功能&#xff1f;Redis支持的数据类型有哪些&#xff1f;Redis为什么这么快…