代码随想录算法训练营第五十九天
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数组看和预期是否有差别。