115.不同的子序列
思路:如果当前下标对应的两个元素大小相同,那么他所储存的相同字串出现的次数由两部分组成:第一部分就是因为s[i-1]==t[j-1],所以dp[i][j]延续了dp[i-1][j-1]的数量,即不变。另一部分是有可能在相等的时候 前面的位置也已经出现了相等的情况,所以应该加上子串的这个位置等于母串的上一个位置的情况,即s[i]=t[j-1],举例bag和bagg 当i=3,j=4时就会出现这种情况。如果两者不相等则只考虑第二种情况。
动规五部曲:
1.dp[i][j] 以nums[i-1]为结尾的子串s中罕有nums[j-1]为结尾的子串t的数量
2.递推公式:若相等dp[i][j]=dp[i-1][j-1]+dp[i-1][j] 在这个位置相等加上 在之前的位置相等 若不相等dp[i][j]=dp[i-1][j]
3.初始化 0
4.遍历顺序 从上到下 从左到右
代码:
class Solution {
public:
int numDistinct(string s, string t) {
//dp[i][j] 以nums[i-1]为结尾的子串s中罕有nums[j-1]为结尾的子串t的数量
//递推公式:若相等dp[i][j]=dp[i-1][j-1]+dp[i-1][j] 在这个位置相等加上 在之前的位置相等
//若不相等dp[i][j]=dp[i-1][j]
//初始化 0
//遍历顺序 从上到下 从左到右
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;
}
int a=pow(10,9)+7;
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])%a;
else dp[i][j]=dp[i-1][j];
}
}
return dp[s.size()][t.size()];
}
};
583. 两个字符串的删除操作
思路:在不相等时,要么删除左面元素,要么删除右面元素,取所需要操作的最小步数,并不断更新。相等时则直接延续,dp[i][j]=dp[i-1][j-1]。
动规五部曲:
1.dp数组下标及其含义 dp[i][j] 使以words1[i-1]为结尾的单词与以words2[j-1]为结尾的单词相同所需的最小步数
2.递推公式 相同 dp[i][j]=dp[i-1][j-1] 不相同 dp[i][j]=min(dp[i][j-1],dp[i-1][j])+1 要删掉不一样的所以要+1
3.初始化 dp[0][0]=0 第一行第一列分别等于行数列数
4.遍历顺序 从上到下 从左到右
代码:
class Solution {
public:
int minDistance(string word1, string word2) {
//删除一次 步数加1
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],dp[i][j-1])+1;
}
}
return dp[word1.size()][word2.size()];
}
};
72. 编辑距离
思路:相比于上一道题目,多了插入和替换操作,插入一个元素所产生的效果其实可以等效于删除一个元素产生的效果(插入少的=删除多的),所以实际上只多了替换操作。在遍历时,我们只需要存储替换和删除中步骤更少的那个值即可
动规五部曲:
1.dp[i][j] 以word1[i-1]为结尾的子串和以word2[j-1]为结尾的子串相同所需要的最少操作数
2.递推公式 相同 dp[i][j]=dp[i-1][j-1] 不相同 删除 =dp[i-1][j]+1 插入=dp[i][j-1]+1 替换=dp[i-1][j-1]+1
3.初始化 dp[i][0]=i dp[0][j]=j
4.遍历顺序 从上到下 从左到右
代码:
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(min(dp[i-1][j-1]+1,dp[i-1][j]+1),dp[i][j-1]+1);
}
}
return dp[word1.size()][word2.size()];
}
};