任务日期:7.20
题目一链接:115. 不同的子序列 - 力扣(LeetCode)
思路:此题与判断子序列的区别在于本题有加和的操作,当s[i - 1] == t[j -1]时,有两种情况,第一是不使用当前元素匹配,第二是使用当前元素匹配;当二者不相同时,此时的dp就等于s删除当前元素的值。
代码:
class Solution {
public:
int numDistinct(string s, string t) {
vector<vector<uint64_t>> dp(s.size() + 1,vector<uint64_t>(t.size() + 1)); //dp[i][j]以下标i - 1为结尾的s的子序列中含有以下标j - 1为结尾的t有dp[i][j]个
//初始化:因为是s的子序列,所以dp[i][0] = 1
for(int i = 0;i <= s.size();i ++) dp[i][0] = 1; // 从零开始到s.size()结束
for(int j = 1;j <= t.size();j ++) dp[0][j] = 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];//两种情况:1是用s[i - 1]来匹配,那么个数为dp[i - 1][j - 1] 2是不用s[i - 1]来匹配,个数为dp[i - 1][j]
else dp[i][j] = dp[i - 1][j];//不用当前元素匹配就相当于删除s中的当前元素
}
}
return dp[s.size()][t.size()];
}
};
难点:1.初始化时dp[i][0]应该都是1,因为s的可以进行删除元素,可以进行删除组成一个空数组,同理dp[0][j]都是零
2.当两个相等时dp的推导需要分两种情况:使用当前的元素匹配和不是用当前的元素匹配。
题目二链接:583. 两个字符串的删除操作 - 力扣(LeetCode)
思路:本题与不同子序列的区别在于本题两个字符串都能删除,因此在word1[]和word2[]不相等时,有两种情况,而由于要得到最小值,所以取min.
代码:
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 = 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);//删除word1里的元素或者删除word2里的元素
}
}
return dp[word1.size()][word2.size()];
}
};
难点:1.初始化时要注意dp数组的含义,根据定义就可求解。
题目三链接:72. 编辑距离 - 力扣(LeetCode)
思路:本题与两个字符的删除操作的区别在于它多了一个替换操作和插入操作,而替换操作实际上就是在相等的情况下多一个操作步骤;一个字符串的插入操作实际就是另一个字符串的删除操作
代码:
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 = 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 ++) { //从1开始是因为0我们已经初始化了
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,dp[i - 1][j - 1] + 1});//没有插入操作,因为插入操作就相当于删除操作
}
}
return dp[word1.size()][word2.size()];
}
};
难点:1.初始化的时候想dp数组的定义即可完成
2.多个式子求最小值用大括号括起来。
3.不理解的地方就像dp[i][j]的定义就能理解了。