代码随想录算法训练营第五十九天
115.不同的子序列
题目链接:115.不同的子序列
- 确定dp数组以及下标的含义:dp[i][j] :以下标i - 1为结尾的s,和以下标j - 1为结尾的t,s中t的个数dp[i][j]
- 确定递推公式:
s[i - 1] == t[j - 1],左边+左上,不考虑当前s、t两个相同字母+s不考虑当前字母t考虑
不等的话s加不加当前字母个数没区别,就等于s不考虑当前字母的个数if (s[i - 1] == t[j - 1]){ dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]; } else{ dp[i][j] = dp[i - 1][j]; }
- dp数组如何初始化:t是空字符串,任意s都有1个空字符串。s是空,都有0个t。
- 确定遍历顺序:从前向后遍历。
- 打印dp数组。
class Solution {
public:
int numDistinct(string s, string t) {
vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1, 0));
for (int i = 0; i <= s.size(); i++) {
dp[i][0] = 1;
}
for (int i = 1; i <= s.size(); i++) {
for (int j = 1; j <= t.size(); j++) {
if (s[i - 1] == t[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.size()][t.size()];
}
};
583. 两个字符串的删除操作
题目链接:583. 两个字符串的删除操作
-
确定dp数组以及下标的含义:dp[i][j] :以下标i - 1为结尾的word1,和以下标j - 1为结尾的word
-
2,删除元素次数dp[i][j]
-
确定递推公式:
两个元素相同,不进行删除操作,次数和不加这两个字母相同就是dp[i-1][j-1]
两个元素不同,删word1当前元素次数+1和删word2当前元素次数+1哪个小取哪个。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); }
-
dp数组如何初始化:word1是空另外一个要删空的次数就是word2中元素的个数就是j,word2是空,另一个要删空的次数就是word1中元素的个数就是i
-
确定遍历顺序:从前向后遍历。
-
打印dp数组。
class Solution {
public:
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));
for (int i = 1; i <= word1.size(); i++) {
dp[i][0] = i;
}
for (int j = 1; 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()];
}
};
72. 编辑距离
题目链接:72. 编辑距离
- 确定dp数组以及下标的含义:dp[i][j] :以下标i - 1为结尾的word1,和以下标j - 1为结尾的word
- 2,编辑元素次数dp[i][j]
- 确定递推公式:
两个元素相同,不进行删除操作,次数和不加这两个字母相同就是dp[i-1][j-1]
两个元素不同,删word1当前元素次数+1和删word2当前元素次数+1哪个小取哪个,替换元素就是不考虑当前的2个元素操作次数+1。if (word1[i - 1] == word2[j - 1]) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = min(min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + 1); }
- dp数组如何初始化:word1是空另外一个要删空的次数就是word2中元素的个数就是j,word2是空,另一个要删空的次数就是word1中元素的个数就是i
- 确定遍历顺序:从前向后遍历。
- 打印dp数组。
class Solution {
public:
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1, 0));
for (int i = 1; i <= word1.size(); i++) {
dp[i][0] = i;
}
for (int j = 1; 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(min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + 1);
}
}
}
return dp[word1.size()][word2.size()];
}
};
编辑距离总结篇
- 两个字符串做匹配,dp数组含义基本为s[i-1]为结尾,t[j-1]为结尾的操作次数或子序列个数…为了方便把dp[i][0]和dp[0][j]空出来方便初始化
- 递推公式一般分为s[i-1]==t[j-1]和不等两种情况
- 初始化时候要考虑dp[i][0]和dp[0][j],其他的位置取任意值即可,因为都会被递推公式覆盖
- 遍历顺序都是从左到右,从上到下。
- 有问题时需打印dp数组看和预期是否有差别。