代码随想录算法训练营第五十四天| ● 392.判断子序列 ● 115.不同的子序列
判断子序列
题目链接:392. 判断子序列 - 力扣(LeetCode)
思路:从子串s开始遍历,查找t中是否存在,因为全程不需要回溯,因此两个for循环就解决了。只是要注意return的时机。(只要不想写的很简洁,逻辑挺简单的其实)
class Solution {
public:
bool isSubsequence(string s, string t) {
if(s.size()>t.size())return false;
int j=0;
for(int i=0;i<s.size();i++){
for(;j<t.size();j++){
if(s[i]==t[j]){
j++;
if(i==s.size()-1&&j==t.size())return true;
break;
}
}
if(j==t.size())return false;
}
return true;
}
};
简洁写法来了,不愧是k神。
class Solution {
public:
bool isSubsequence(string s, string t) {
if (s.size() == 0) return true;
for (int i = 0, j = 0; j < t.size(); j++) {
if (s[i] == t[j]) {
// 若已经遍历完 s ,则提前返回 true
if (++i == s.size())
return true;
}
}
return false;
}
};
作者:Krahets
链接:https://leetcode.cn/problems/is-subsequence/solutions/1658262/by-jyd-zeph/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
不同的子序列
题目链接:115. 不同的子序列 - 力扣(LeetCode)
思路:第一思路是想到和过去写的回溯很像,因此想用回溯写,但是……
class Solution {
public:
int result;
void backtracking(string s,string t,int sindex,int tindex){
if(tindex==t.size()){
result++;
}
for(int i=sindex;i<s.size();i++){
if(s[i]==t[tindex]){
backtracking(s,t,i+1,tindex+1);
}
}
}
int numDistinct(string s, string t) {
if(s.size()<t.size())return 0;
int mod = 1000000000 + 7;
backtracking(s,t,0,0);
return result%mod;
}
};
只能学习官网的dp方法了。dp[i][j]:以i-1为结尾的s子序列中出现以j-1为结尾的t的个数为dp[i][j]。
dp[i][0] 表示:以i-1为结尾的s可以随便删除元素,出现空字符串的个数。
那么dp[i][0]一定都是1,因为也就是把以i-1为结尾的s,删除所有元素,出现空字符串的个数就是1。
再来看dp[0][j],dp[0][j]:空字符串s可以随便删除元素,出现以j-1为结尾的字符串t的个数。
那么dp[0][j]一定都是0,s如论如何也变成不了t。
最后就要看一个特殊位置了,即:dp[0][0] 应该是多少。
dp[0][0]应该是1,空字符串s,可以删除0个元素,变成空字符串t。
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()];
}
};