Leetcode: 392. 判断子序列

时间复杂度: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;
}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值