代码随想录Day39动态规划:115不同的子序列_583两个字符串的删除操作_72编辑距离_编辑距离总结

代码随想录Day39动态规划:115不同的子序列_583两个字符串的删除操作_72编辑距离_编辑距离总结

115不同的子序列

题目:给你两个字符串s和t,统计并返回在s的子序列中t出现的个数。测试用例保证结果在 32 位有符号整数范围内。

示例 1:输入:s = "rabbbit", t = "rabbit",输出:3

解释:如下所示, 有 3 种可以从 s 中得到 "rabbit" 的方案。

链接:https://leetcode.cn/problems/distinct-subsequences/

动规五部曲:
1 确定dp数组及其含义

dpij:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dpij

以i-1为结尾的s子序列中出现dpij个以j-1为结尾的t。

2 确定递推公式

这一类问题,基本是要分析两种情况

si - 1 与 tj - 1相等

si - 1 与 tj - 1 不相等

当si - 1 与 tj - 1相等时,dpij可以有两部分组成。一部分是用si - 1来匹配,那么个数为dpi - 1j - 1。即不需要考虑当前s子串和t子串的最后一位字母,所以只需要 dpi-1j-1。一部分是不用si - 1来匹配,个数为dpi - 1j。所以当si - 1 与 tj - 1相等时,dpij = dpi - 1j - 1 + dpi - 1j;

当si - 1 与 tj - 1不相等时,dpij只有一部分组成,不用si - 1来匹配(就是模拟在s中删除这个元素),即:dpi - 1j。所以递推公式为:dpij = dpi - 1j;

3 初始化dp数组

每次当初始化的时候,都要回顾一下dpij的定义,不要凭感觉初始化。

dpi0 表示:以i-1为结尾的s可以随便删除元素,出现空字符串的个数。

那么dpi0一定都是1,因为也就是把以i-1为结尾的s,删除所有元素,出现空字符串的个数就是1。

dp0j:空字符串s可以随便删除元素,出现以j-1为结尾的字符串t的个数。

那么dp0j一定都是0,s如论如何也变成不了t。

dp00应该是1,空字符串s,可以删除0个元素,变成空字符串t。

4 确定遍历顺序

从上到下,从左到右
5 举例推导dp数组

java 复制代码
class Solution {
    public int numDistinct(String s, String t) {
        int[][] dp=new int[s.length()+1][t.length()+1];
        for(int i=0;i<=s.length();i++){
            dp[i][0]=1;
        }

        for(int i=1;i<=s.length();i++){
            for(int j=1;j<=t.length();j++){
                if(s.charAt(i-1)==t.charAt(j-1)){
                    dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
                }else{
                    dp[i][j]=dp[i-1][j];
                }
            }
        }
        return dp[s.length()][t.length()];
    }
}

583两个字符串的删除操作

题目:给定两个单词word1和word2,返回使得word1和word2相同所需的最小步数。每步可以删除任意一个字符串中的一个字符。

示例1:输入: word1 = "sea", word2 = "eat",输出: 2

解释: 第一步将 "sea" 变为 "ea" ,第二步将 "eat "变为 "ea"

链接:https://leetcode.cn/problems/delete-operation-for-two-strings/

和之前题目的区别是:现在两个字符串都可以删了。

动规五部曲:
1 确定dp数组以及下标的含义

dpij以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。

2 确定递推公式

当word1i - 1 与 word2j - 1相同的时候

当word1i - 1 与 word2j - 1不相同的时候

当word1i - 1 与 word2j - 1相同的时候,dpij = dpi - 1j - 1;

当word1i - 1 与 word2j - 1不相同的时候,有三种情况:

情况一:删word1i - 1,最少操作次数为dpi - 1j + 1

情况二:删word2j - 1,最少操作次数为dpij - 1 + 1

情况三:同时删word1i - 1和word2j - 1,操作的最少次数为dpi - 1j - 1 + 2

那最后当然是取最小值,所以当word1i - 1 与 word2j - 1不相同的时候,递推公式:dpij = min({dpi - 1j - 1 + 2, dpi - 1j + 1, dpij - 1 + 1});

因为 dpij - 1 + 1 = dpi - 1j - 1 + 2,所以递推公式可简化为:dpij = min(dpi - 1j + 1, dpij - 1 + 1);

3 dp数组初始化

从递推公式中可以看出,dpi0 和 dp0j是一定要初始化的。

dpi0:word2为空字符串,以i-1为结尾的字符串word1要删除多少个元素,才能和word2相同呢,很明显dpi0 = i。dp0j的话同理。

4 遍历顺序

从上到下,从左到右

5 举例推导dp数组

java 复制代码
class Solution {
    public int minDistance(String word1, String word2) {
        int len1=word1.length();
        int len2=word2.length();
        int[][] dp=new int[len1+1][len2+1];

        for(int i=0;i<=len1;i++) dp[i][0]=i;
        for(int j=0;j<=len2;j++) dp[0][j]=j;

        for(int i=1;i<=len1;i++){
            for(int j=1;j<=len2;j++){
                if(word1.charAt(i-1)==word2.charAt(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]+2));
                }
            }
        }
        return dp[len1][len2];
    }
}

72编辑距离

题目:给你两个单词word1和word2,请返回将word1 转换成word2所使用的最少操作数。你可以对一个单词进行如下三种操作:插入一个字符,删除一个字符,替换一个字符。

示例 1:输入:word1 = "horse", word2 = "ros",输出:3

解释:horse -> rorse (将 'h' 替换为 'r')

rorse -> rose (删除 'r')

rose -> ros (删除 'e')

链接:https://leetcode.cn/problems/edit-distance/

动规五部曲:
1 确定dp数组及其含义

dpij 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dpij

2 确定递归公式

两种情况:word1i - 1 == word2j - 1和 word1i - 1 != word2j - 1

if (word1i - 1 == word2j - 1) 那么说明不用任何编辑,dpij 就应该是 dpi - 1j - 1,即dpij = dpi - 1j - 1;

if (word1i - 1 != word2j - 1),就需要编辑了。

操作一:word1删除一个元素,那么就是以下标i - 2为结尾的word1 与 j-1为结尾的word2的最近编辑距离 再加上一个操作。即 dpij = dpi - 1j + 1;

操作二:word2删除一个元素,那么就是以下标i - 1为结尾的word1 与 j-2为结尾的word2的最近编辑距离 再加上一个操作。即 dpij = dpij - 1 + 1;

怎么都是删除元素,添加元素去哪了。word2添加一个元素,相当于word1删除一个元素,例如 word1 = "ad" ,word2 = "a",word1删除元素'd' 和 word2添加一个元素'd',变成word1="a", word2="ad", 最终的操作数是一样。

操作三:替换元素,word1替换word1i - 1,使其与word2j - 1相同,此时不用增删加元素。if (word1i - 1 == word2j - 1)的时候我们的操作是 dpij = dpi - 1j - 1。那么只需要一次替换的操作,就可以让 word1i - 1 和 word2j - 1 相同。所以 dpij = dpi - 1j - 1 + 1;

综上,当 if (word1i - 1 != word2j - 1) 时取最小的,即:dpij = min({dpi - 1j - 1, dpi - 1j, dpij - 1}) + 1;

3 dp数组初始化

dpij 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dpij

那么dpi0 :以下标i-1为结尾的字符串word1,和空字符串word2,最近编辑距离为dpi0。那么dpi0就应该是i,对word1里的元素全部做删除操作,即:dpi0 = i; 同理dp0j = j。

4 遍历顺序

从左到右从上到下去遍历
5 举例推导dp数组

java 复制代码
class Solution {
    public int minDistance(String word1, String word2) {
        int len1=word1.length();
        int len2=word2.length();
        int[][] dp=new int[len1+1][len2+1];

        for(int i=0;i<=len1;i++){
            dp[i][0]=i;
        }
        for(int j=0;j<=len2;j++){
            dp[0][j]=j;
        }

        for(int i=1;i<=len1;i++){
            for(int j=1;j<=len2;j++){
                if(word1.charAt(i-1)==word2.charAt(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));
                }
            }
        }
        return dp[len1][len2];
    }
}

编辑距离总结

392判断子序列给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

115不同的子序列给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

583两个字符串的删除操作给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最少步数,每步可以删除任意一个字符串中的一个字符。

72编辑距离给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数。

相关推荐
小雨下雨的雨25 分钟前
井字棋AI机器人实现详解 - Minimax算法实战-鸿蒙PC Electron框架完成
前端·人工智能·算法·华为·electron·鸿蒙
xieliyu.3 小时前
Java算法精讲:双指针(三)
java·开发语言·算法
一条小锦吕*3 小时前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化
如竟没有火炬5 小时前
最大矩阵——单调栈
数据结构·python·线性代数·算法·leetcode·矩阵
8Qi85 小时前
LeetCode 1143 & 718:最长公共子序列 / 最长重复子数组
算法·leetcode·职场和发展·动态规划
绿算技术6 小时前
万卡推理集群存储选型分析:从核心架构到应用视角
大数据·科技·算法·架构
想吃火锅10057 小时前
【leetcode】1.两数之和js版
javascript·算法·leetcode
net3m338 小时前
一阶软件低通滤波器算法
人工智能·算法
水木流年追梦8 小时前
大模型入门-大模型优化方法12-YaRN 长文本外推技术
人工智能·分布式·算法·正则表达式·prompt