两个字符串的删除操作
- leetcode583. 两个字符串的删除操作
- 题目描述
- 解题思路
- 解法一 递归加缓存
- 动态规划
- 代码演示
- 动态规划专题
leetcode583. 两个字符串的删除操作
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/delete-operation-for-two-strings
题目描述
给定两个单词 word1 和 word2 ,返回使得 word1 和 word2 相同所需的最小步数。
每步 可以删除任意一个字符串中的一个字符。
示例 1:
输入: word1 = “sea”, word2 = “eat”
输出: 2
解释: 第一步将 “sea” 变为 “ea” ,第二步将 "eat "变为 “ea”
示例 2:
输入:word1 = “leetcode”, word2 = “etco”
输出:4
提示:
1 <= word1.length, word2.length <= 500
word1 和 word2 只包含小写英文字母
解题思路
这题最直观的思考还是暴力递归,用两个指针,卡住两个单词的起始位置,如果相同,同时跳到下一个位置,如果不同,就有两种情况了,是单词1删除还是单词2删除,因为要求出最小步数,所以,我们要两种情况都去考虑,要最小值.
解法一 递归加缓存
/**
* 最小步数
* @param word1
* @param word2
* @return
*/
public int minDistance(String word1, String word2) {
int n = word1.length();
int m = word2.length();
int[][] dp = new int[n + 1][m + 1];
return process(word1.toCharArray(),n - 1,word2.toCharArray(),m - 1,dp);
}
/**
* 暴力递归加缓存
* @param word1
* @param i
* @param word2
* @param j
* @param dp
* @return
*/
public int process(char[] word1,int i,char[] word2,int j,int[][]dp){
if (i == -1 && j == -1){
return 0;
}
if (i == -1){
return j + 1;
}
if (j == -1){
return i + 1;
}
if (dp[i][j] != 0){
return dp[i][j];
}
int res = 0;
//相等时,当前不做操作,等于下一个位置,
if(word1[i] == word2[j]){
res = process(word1,i - 1,word2, j - 1,dp);
}else{
//word1 删除
int p1 = process(word1,i - 1,word2,j ,dp);
//word2 删除
int p2 = process(word1,i ,word2,j - 1,dp);
//取两种情况最小步数,加上当前字符本身操作,
res = Math.min(p1,p2) + 1;
}
dp[i][j] = res;
return res;
}
动态规划
暴力递归改动态规划,分为三个步骤,
1.初始化dp表
2.把递归过程改成从表中拿值的过程
3.返回dp表数据
先看下如何初始化,如果word1 长度为0 时,那么操作的次数就是把word2 全部删除,就是word2 的长度,反之,word2 长度是0 的时候,需要操作的步数就是word1 的长度,由此我们可以初始化出表中的数据,
如图演示:
第一行和第一列就可以初始出来了,
操作时,从1开始,比较时别忘记减1.
代码演示
/**
* 动态规划
* @param word1
* @param word2
* @return
*/
public int minDistance(String word1, String word2){
int n = word1.length();
int m = word2.length();
int[][] dp = new int[n + 1][m + 1];
//第一行
for (int i = 1;i <= m;i++){
dp[0][i] = i;
}
//第一列
for (int j = 1; j <= n;j++){
dp[j][0] = j;
}
for (int i = 1; i <= n;i++){
for (int j = 1; j <= m;j++){
//比较时,要减1,下标从0开始的
if (word1.charAt(i - 1) == word2.charAt(j - 1)){
dp[i][j] = dp[i - 1][j - 1];
}else{
int p1 = dp[i - 1][j];
int p2 = dp[i][j - 1];
dp[i][j] = Math.min(p1,p2) + 1;
}
}
}
return dp[n][m];
}
动态规划专题
leetcode514. 自由之路
leetcode887. 鸡蛋掉落
leetcode1884. 鸡蛋掉落-两枚鸡蛋
leetcode312. 戳气球
leetcode787. K 站中转内最便宜的航班
leetcode62. 不同路径