时间复杂度:O(n)
方法一:直接O(n)
class Solution {
public:
bool isSubsequence(string s, string t) {
if(s.size()==0)
return true;
int a = 0;
for(int i=0;i<t.size();i++){
if(s[a] == t[i])
a++;
if(a == s.size()) //判断是不是子序列出现的有问题的时候
{
return true;
}
}
return false;
}
};
题解二. 后续挑战,输入量大,小写字母创建25的二维数组,存储t的坐标,这样就可以把s的判断直接转为坐标的判断。
dp[0]代表了存储了a出现在t的所有的位置,逐个字符判断s的字符顺序是否在t内,直接返回结果。
时间复杂度O(t.size()+2000):分别为创建数组需要O(t.size()),
索引是递增的使用二分查找s的单个字符20次之内就可找到需要O(100*20)。
适用大量的输入判断子序列。
bool isSubsequence(string s, string t) {
vector<vector<int>>dp(26);
int tag=-1;
for(int i=0;i<t.size();i++)
dp[t[i]-'a'].push_back(i);
for(int i=0;i<s.size();i++){
int now=s[i]-'a';
int left=0,right=dp[now].size()-1;
while(left<right){
int mid=(left+right)/2;
if(dp[now][mid]>tag)
right=mid;
else
left=mid+1;
}
if(right<left || dp[now][left]<=tag) //对于这个判断条件不是很理解的
return false;
tag=dp[now][left];
}
return true;
}
注意:vector不进行初始化默认的是0。
- 前面的是别人的方法,我也采用这种办法的,小写字母创建25的二维数组,存储t的坐标,这样就可以把s的判断直接转为坐标的判断,因为这样使用,判断多次的s得时候,不用反复加载t,节省时间。
- 最后采用普通方式代替二分法。每次的标签tag大于当前的数组的最大长度,返回错误。或者字符在t之中根本没有出现过,也返回错误。
class Solution {
public:
bool isSubsequence(string s, string t) {
vector<vector<int>>dp(26);
int tag=-1;
for(int i=0;i<t.size();i++)
dp[t[i]-'a'].push_back(i);
for(int i=0;i<s.size();i++){
int now=s[i]-'a';
int lenth = dp[now].size();
if(lenth == 0)
return false;
for(int j = 0; j<=lenth-1;j++){
if(tag>=dp[now][lenth-1])
return false;
if(tag<dp[now][j]){
tag = dp[now][j];
break;
}
if(tag>=dp[now][j] && tag<dp[now][j+1]){
tag = dp[now][j+1];
break;
}
}
}
return true;
}
};