持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情
一、题目
LeetCode 两个字符串的删除操作
给定两个单词 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 只包含小写英文字母
二、题解
方法一
每一步操作可以删除两个字符串中的某些字符,来使得这两个字符串剩余的字符相同,如果存在这个字符串,那么这个字符串就必定是两个字符串的子序列,而要使得操作的步数最少也就是删除的字符数量最少,那么这个子序列其实就是两个字符串的最长公共子序列。所以可以通过求出两个字符串的最长公共子序列,然后在于原字符串对比字符数量,这个字符数量差就是需要执行删除字符的步骤数,也就是最少的了。
方法二
或者直接通过动态规划来计算需要操作的最小次数,定义一个与字符串word1和字符串word2长度加一(需要初始化第一个字符前的状态)的二维数组dp,那么dp[i][j]就表示使字符串word1下标i之前字符和字符串word2下标j之前字符相同需要的最小操作次数。初始的当i = 0时,字符串word2下标j之前字符都需要删除才能够使得两个字符相同,同样的当j = 0时,字符串word1下标i之前字符都需要删除才能够使得两个字符相同。然后可以双重遍历字符串的字符,对应字符串word1的字符char1和字符串word2的字符char2来说,如果char1等于char2的话,两个字符是一样的话就不需要进行删除操作以保持最小的操作次数,所以dp[i][j]就等于dp[i - 1][j - 1];如果char1不等于char2的话,说明就需要进行删除字符操作来使得两个字符串相同,如果要使得word1[i - 1]和word2[j]相同就需要删除word1[i]字符,同理要使word1[i]和word2[j - 1]相同就需要删除word1[j]字符,所以dp[i][j]就等于min(dp[i - 1][j], dp[i][j - 1])加上一个删除次数。最后遍历结束的dp数组最后一个元素就是最小的删除次数。
三、代码
方法一 Java代码
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];
for (int i = 1; i <= m; i++) {
char char1 = word1.charAt(i - 1);
for (int j = 1; j <= n; j++) {
char char2 = word2.charAt(j - 1);
if (char1 == char2) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
int max = dp[m][n];
return m - max + n - max;
}
}
时间复杂度:O(n^2),需要双重循环遍历两个字符串的字符来计算。
空间复杂度:O(n^2),需要定义一个二维数组。
方法二 Java代码
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];
for (int i = 1; i <= m; i++) {
dp[i][0] = i;
}
for (int j = 1; j <= n; j++) {
dp[0][j] = j;
}
for (int i = 1; i <= m; i++) {
char char1 = word1.charAt(i - 1);
for (int j = 1; j <= n; j++) {
char char2 = word2.charAt(j - 1);
if (char1 == char2) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + 1;
}
}
}
return dp[m][n];
}
}
时间复杂度:O(n^2),需要双重循环遍历两个字符串的字符来计算。
空间复杂度:O(n^2),需要定义一个二维数组。