leetcode 392. 判断子序列
题目链接:判断子序列
- 确定dp数组及下标的含义
dp[i][j]
:以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列长度为dp[i][j] - 确定递推公式
分为两种情况:s[i - 1] 与t[j - 1]相同,s[i - 1] 与 t[j - 1]不相同
(1)s[i - 1] 与 t[j - 1]相同:找到一个相同字符,dp[i][j] = dp[i - 1][j - 1] + 1
(2)s[i - 1] 与 t[j - 1]不相同:此时相当于t要删除元素,t如果把t[j - 1]删除,那么dp[i][j] 的数值是看s[i - 1]与 t[j - 2]的比较结果,dp[i][j] = dp[i][j - 1]
本题与 leetcode 1143.最长公共子序列 的区别是如果删元素一定是字符串t,而 leetcode 1143.最长公共子序列 是两个字符串都可以删元素。
- dp数组初始化
vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1, 0));
- 确定遍历顺序
从前到后,从上到下
如果dp[s.size()][ t.size()] 与字符串 s 的长度相同说明 s 与 t 的最长相同子序列就是s,则 s 就是 t 的子序列。
class Solution {
public:
bool isSubsequence(string s, string t) {
vector<vector<int>> dp(s.size() + 1, vector<int>(t.size() + 1, 0));
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] + 1;
else dp[i][j] = dp[i][j - 1];
}
}
if (dp[s.size()][t.size()] == s.size()) return true;
return false;
}
};
时间复杂度:O(n × m)
空间复杂度:O(n × m)
leetcode 115. 不同的子序列
题目链接:不同的子序列
- 确定dp数组及下标的含义
dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j] - 确定递推公式
分析两种情况:s[i-1]与t[j-1]相等;s[i-1]与t[j-1]不相等
(1)当s[i - 1] 与 t[j - 1]相等时:分为两部分,一部分是用s[i - 1]来匹配,个数为dp[i - 1][j - 1];一部分是不用s[i - 1]来匹配,个数为dp[i - 1][j],则dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j]
(2)当s[i - 1] 与 t[j - 1]不相等时:dp[i][j]只有一部分组成,不用s[i - 1]来匹配(模拟s种删除元素),则dp[i][j] = dp[i - 1][j]
- dp数组初始化
vector<vector<long long>> dp(s.size() + 1, vector<long long>(t.size() + 1));
for (int i = 0; i <= s.size(); i++) dp[i][0] = 1;
for (int j = 1; j <= t.size(); j++) dp[0][j] = 0;
- 确定遍历顺序
dp[i][j]都是根据左上方和正上方推出:
所以遍历顺序是从上到下,从左到右
class Solution {
public:
int numDistinct(string s, string t) {
vector<vector<uint64_t>> dp(s.size() + 1, vector<uint64_t>(t.size() + 1));
for (int i = 0; i < s.size(); i++) dp[i][0] = 1;
for (int j = 1; j < t.size(); j++) dp[0][j] = 0;
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()];
}
};
时间复杂度: O(n * m)
空间复杂度: O(n * m)