目录
583. 两个字符串的删除操作
看到题目的第一想法
看到代码随想录之后的想法
自己实现过程中遇到的困难(看代码)
72. 编辑距离
看到题目的第一想法
看到代码随想录之后的想法
自己实现过程中遇到的困难(看代码)
583. 两个字符串的删除操作
力扣题目链接(opens new window)
给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。
示例:
- 输入: "sea", "eat"
- 输出: 2
- 解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"
看到题目的第一想法
按照求最长子序列的思路来做,得到最长的公共length值,用两个字符串的长度减去两个公共length 就是最长公共子序列的长度
公共最长子序列的求法
dp[i][j] 为0~i-1 0~j-1的最长序列
递推公式
若相同,dp[i][j] = dp[i-1][j-1]+1
若不相同,二选一 dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
看到代码随想录之后的想法
用动态规划,使用了删除的思路
(选中两个单词的字符,判断删除哪一个)
确定dp数组和每个下标的含义
dp[i][j]记录末尾为i-1和j-1的最少删除字符的个数
确定递推公式
要从递推公式来进行考虑
若word1[i] = word2[j] 则不管是否选中word1 和word2 和不选中word1和word2都一样,不需要新增删除的次数,总删除的次数和之前相等
dp[i][j] = dp[i-1][j-1];
若word1[i] !=word2[j] 则从之前的删除次数最小值 来考虑
若选中word1来删除
之前的总删除次数为dp[i-1][j]+1
若选中word2来删除
之前的总删除次数为dp[i][j-1]+1
若都不选中,两者都删
之前的总删除次数为dp[i-1][j-1]+2
之前的最长子序列是dp[i][j] = Math.min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+2);
dp数组初始化
因为dp[i][j] 代表0~i-1,0~j-1的最大删除次数,
则dp[i][0] = i
dp[0][j] = j (含义:若把j变成0 需要删除j次)
确定遍历顺序
从前往后,从上往下
举例推导dp数组
打印dp数组
打印最后一个元素文章来源:https://www.toymoban.com/news/detail-819882.html
自己实现过程中遇到的困难(看代码)
疑问?为什么选最小的?不相同时不应该两个都要删吗?
不是两个都要删,而是判断不相同了,一次只删一个,选择哪一个
两个不相等,模拟一下这个双重循环,其实i固定不变,只是在动j
遇到两个单词中不相等的字符,来通过dp来判断应该删除哪一个,二维数组是动态变化的
最小的删除个数,从之前中选择最小的
class Solution {
public int minDistance(String word1, String word2) {
/*
//我的做法
//相同的最小步数
//其实就是看公共子序列的最大长度?,然后看删去需要多少个字符?
//确定dp的定义和下标的含义
// dp[i][j] 0~i-1的word1 和 0~j-1的相同公共子序列的长度
//确定递推公式
// 若word[i-1]==word[j-1] 则dp[i][j]=dp[i-1][j-1]+1
// 若不相等 则dp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);
//dp数组初始化
// 都为0
//确定遍历顺序
// 从上往下,从左至右
//打印dp数组
int[][] dp = new int[word1.length()+1][word2.length()+1];
for(int i=1;i<=word1.length();i++){
for(int j=1;j<=word2.length();j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1]+1;
}else{
dp[i][j] = Math.max(dp[i][j-1],dp[i-1][j]);
}
}
}
int maxLength = dp[word1.length()][word2.length()];
return word1.length()+word2.length()-2*maxLength;*/
//卡哥的做法
//确定dp的定义和下标的含义
// dp[i][j] 代表删除字符的最小的个数
//确定递推公式
// 如何删除
// word1[i-1]==word2[j-1] 若相等 考虑选中word1[i-1] 和word2[j-1] 和不选中word1[i-1]和word2[j-1]
// dp[i][j] = dp[i-1][j-1],因为相等,所以 都考虑和都不考虑,最小删除的个数都是一样的
// word1[i]!=word2[j] 若不相等 ,考虑最小删除的个数,有三种情况
// 若不选中word1 则为 dp[i-1][j]+1
// 若不选中word2 则为 dp[i][j-1]+1
// 若不都选中 dp[i-1][j-1] +2 去三者中的最小值
//dp数组初始化
// dp[i][0] = i word1 有值,word2为空串
// dp[0][j] = j word2 有值,word1为空串
//确定遍历顺序
// 从上往下,从左至右
//打印dp数组
int dp[][] = new int[word1.length()+1][word2.length()+1];
for(int i=0;i<=word1.length();i++){
dp[i][0] = i;
}
for(int j=0;j<=word2.length();j++){
dp[0][j] = j;
}
for(int i=1;i<=word1.length();i++){
for(int j=1;j<=word2.length();j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}else{
// 疑问?为什么选最小的?不相同时不应该两个都要删吗?
// 不是两个都要删,而是判断不相同了,一次只删一个,选择哪一个
// 两个不相等,模拟一下这个双重循环,其实i固定不变,只是在动j
// 看两个单词中不相等的字符,来看通过dp来判断应该删除哪一个,二维数组是动态变化的
//最小的删除个数,从之前中选择最小的
dp[i][j] = Math.min(dp[i-1][j]+1,dp[i][j-1]+1);
}
}
}
return dp[word1.length()][word2.length()];
}
}
72. 编辑距离
力扣题目链接(opens new window)
给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
-
插入一个字符
-
删除一个字符
-
替换一个字符
-
示例 1:
-
输入:word1 = "horse", word2 = "ros"
-
输出:3
-
解释: horse -> rorse (将 'h' 替换为 'r') rorse -> rose (删除 'r') rose -> ros (删除 'e')
-
示例 2:
-
输入:word1 = "intention", word2 = "execution"
-
输出:5
-
解释: intention -> inention (删除 't') inention -> enention (将 'i' 替换为 'e') enention -> exention (将 'n' 替换为 'x') exention -> exection (将 'n' 替换为 'c') exection -> execution (插入 'u')
提示:
- 0 <= word1.length, word2.length <= 500
- word1 和 word2 由小写英文字母组成
看到题目的第一想法
按上一题的思路来做
看到代码随想录之后的想法
用动态规划,使用了删除的思路
(选中两个单词的字符,判断删除哪一个)
确定dp数组和每个下标的含义
dp[i][j]记录末尾为i-1和j-1的最少删除字符的个数
确定递推公式
要从递推公式来进行考虑
若word1[i] = word2[j] 则不管是否选中word1 和word2 和不选中word1和word2都一样,不需要新增删除的次数,总删除的次数和之前相等
dp[i][j] = dp[i-1][j-1];
若word1[i] !=word2[j] 则从之前的操作次数最小值 来考虑
若选中word1来操作一次 (之前的基础上+1)
替换
将两个元素看成相等的,那么dp[i][j] = dp[i-1][j-1]+1
新增和删除
之前的总操作次数为dp[i-1][j],在这个基础上+1
若选中word2来操作同理
dp数组初始化
因为dp[i][j] 代表0~i-1,0~j-1的最大操作次数,
则dp[i][0] = i
dp[0][j] = j (含义:若把j变成0 需要删除j次)
确定遍历顺序
从前往后,从上往下
举例推导dp数组
打印dp数组
打印最后一个元素
自己实现过程中遇到的困难(看代码)
文章来源地址https://www.toymoban.com/news/detail-819882.html
class Solution {
public int minDistance(String word1, String word2) {
//word1 转换成word2需要的最小操作数
//word1 转换成word2 需要的最小操作数、其实对于word2也能进行操作
//dp[i][j]代表最小操作数 再进行插入?
//若相等
//dp[i][j] = dp[i-1][j-1]
//若不相等
//替换:可以视为最终目的让两个元素相等,按两个元素相等来看
//dp[i][j] = dp[i-1][j-1]+1
//删除:就是删
// dp[i][j] = dp[i][j-1]+1;
//插入:和删除一样,只是逆向操作而已
// dp[i][j] = dp[i][j-1]+1;
//dp数组初始化
//两个单词都能操作
//dp[i][0] = i
//dp[0][j] = j
int[][] dp = new int[word1.length()+1][word2.length()+1];
for(int i=0;i<=word1.length();i++){
dp[i][0] = i;
}
for(int j=0;j<=word2.length();j++){
dp[0][j] = j;
}
for(int i=1;i<=word1.length();i++){
for(int j=1;j<=word2.length();j++){
if(word1.charAt(i-1)==word2.charAt(j-1)){
dp[i][j] = dp[i-1][j-1];
}else{
//替换:为dp[i-1][j-1]+1(判断最小值时不能省略这一步)
//为什么上一题可以省略这一步呢?
//上一题是求的删除的最小次数,上一题是dp[i-1][j-1]+2 代表两者都不选中时,全删
//删除和新增:为dp[i-1][j]+1,dp[i][j-1]+1的最小值
dp[i][j] = Math.min(dp[i-1][j-1]+1,Math.min(dp[i-1][j]+1,dp[i][j-1]+1));
}
}
}
return dp[word1.length()][word2.length()];
}
}
到了这里,关于动态规划Day16(编辑距离,删除元素待写完)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!