php做网站有哪些好处,58同城建网站怎么做,网络建设工程师是干什么的,专业定制房地产网站建设代码随想录算法训练营第59天#xff1a;动态 两个字符串的删除操作
力扣题目链接(opens new window)
给定两个单词 word1 和 word2#xff0c;找到使得 word1 和 word2 相同所需的最小步数#xff0c;每步可以删除任意一个字符串中的一个字符。
示例#xff1a;
输入: …代码随想录算法训练营第59天动态 两个字符串的删除操作
力扣题目链接(opens new window)
给定两个单词 word1 和 word2找到使得 word1 和 word2 相同所需的最小步数每步可以删除任意一个字符串中的一个字符。
示例
输入: “sea”, “eat”输出: 2解释: 第一步将sea变为ea第二步将eat变为ea
#算法公开课
《代码随想录》算法视频公开课 ****(opens new window)**** LeetCode583.两个字符串的删除操 ****(opens new window)**** 相信结合视频再看本篇题解更有助于大家对本题的理解。
#思路
#动态规划一
本题和动态规划115.不同的子序列 **(opens new window)** 相比其实就是两个字符串都可以删除了情况虽说复杂一些但整体思路是不变的。
这次是两个字符串可以相互删了这种题目也知道用动态规划的思路来解动规五部曲分析如下
确定dp数组dp table以及下标的含义
dp[i][j]以i-1为结尾的字符串word1和以j-1位结尾的字符串word2想要达到相等所需要删除元素的最少次数。
这里dp数组的定义有点点绕大家要撸清思路。
确定递推公式
当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 - 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
那最后当然是取最小值所以当word1[i - 1] 与 word2[j - 1]不相同的时候递推公式dp[i][j] min({dp[i - 1][j - 1] 2, dp[i - 1][j] 1, dp[i][j - 1] 1});
因为 dp[i][j - 1] 1 dp[i - 1][j - 1] 2所以递推公式可简化为dp[i][j] min(dp[i - 1][j] 1, dp[i][j - 1] 1);
这里可能不少录友有点迷糊从字面上理解 就是 当 同时删word1[i - 1]和word2[j - 1]dp[i][j-1] 本来就不考虑 word2[j - 1]了那么我在删 word1[i - 1]是不是就达到两个元素都删除的效果即 dp[i][j-1] 1。
dp数组如何初始化
从递推公式中可以看出来dp[i][0] 和 dp[0][j]是一定要初始化的。
dp[i][0]word2为空字符串以i-1为结尾的字符串word1要删除多少个元素才能和word2相同呢很明显dp[i][0] i。
dp[0][j]的话同理所以代码如下
vectorvectorint dp(word1.size() 1, vectorint(word2.size() 1));
for (int i 0; i word1.size(); i) dp[i][0] i;
for (int j 0; j word2.size(); j) dp[0][j] j;确定遍历顺序
从递推公式 dp[i][j] min(dp[i - 1][j - 1] 2, min(dp[i - 1][j], dp[i][j - 1]) 1); 和dp[i][j] dp[i - 1][j - 1]可以看出dp[i][j]都是根据左上方、正上方、正左方推出来的。
所以遍历的时候一定是从上到下从左到右这样保证dp[i][j]可以根据之前计算出来的数值进行计算。
举例推导dp数组
以word1:“sea”word2:eat为例推导dp数组状态图如下
以上分析完毕代码如下
class Solution {
public:
int minDistance(string word1, string word2) {
vectorvectorint dp(word1.size() 1, vectorint(word2.size() 1));
for (int i 0; i word1.size(); i) dp[i][0] i;
for (int j 0; j word2.size(); j) dp[0][j] j;
for (int i 1; i word1.size(); i) {
for (int j 1; j word2.size(); j) {
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][j - 1] 1);
}
}
}
return dp[word1.size()][word2.size()];
}
};
时间复杂度: O(n * m)空间复杂度: O(n * m)
#动态规划二
本题和动态规划1143.最长公共子序列 **(opens new window)** 基本相同只要求出两个字符串的最长公共子序列长度即可那么除了最长公共子序列之外的字符都是必须删除的最后用两个字符串的总长度减去两个最长公共子序列的长度就是删除的最少步数。
代码如下
class Solution {
public:
int minDistance(string word1, string word2) {
vectorvectorint dp(word1.size()1, vectorint(word2.size()1, 0));
for (int i1; iword1.size(); i){
for (int j1; jword2.size(); j){
if (word1[i-1] word2[j-1]) dp[i][j] dp[i-1][j-1] 1;
else dp[i][j] max(dp[i-1][j], dp[i][j-1]);
}
}
return word1.size()word2.size()-dp[word1.size()][word2.size()]*2;
}
};
时间复杂度: O(n * m)空间复杂度: O(n * m)