LeetCode--30.串联所有单词的子串

前言:这道题我做得有点崩溃,前前后后做了很多次,一直都卡在倒数第二个测试用例没有通过,

本来是没打算发这道题的,因为没怎么通过,但想了一下,我修改代码的过程还是蛮宝贵的,所以就打算还是发出来启发一下你怎么修改代码,所以,这道题没什么参考价值,我就随便写写咯

解题思路:

        1.获取信息:

                (1)给定一个字符串和字符串数组,要求按任意顺序组合字符串数组中所有的字符串

                         再检验组合成的字符串是否是给定的那个字符串的子串

                         如果是,就记录下子串的首字符在给定字符串的下标

                (2)它给了例子,可以结合例子理解一下

                (3)那些首字符的下标们可以按任意顺序返回哦

        2.分析题目:

                这道题让我想到了力扣第28题,这道题的匹配字符串环节大概就是第28题,第28题我使用了两种方法,一种是滑动窗口法来匹配,一种是KMP算法

                这道题我就选用滑动窗口法来进行这一步骤,一方面是简化这道题,让它比较好理解,一方面是给自己上上强度

                这样我们就将这道题拆分成了两个小问题了,其中一个小问题,匹配子串,我们已经知道怎么解决了,另一个小问题,就是该怎么获得字符串数组中字符串组合后形成的字符串了

                具体获取方法,我会放在下面的方法结合代码来帮助你理解

        3.示例查验:

                示例1,示例2和示例3:你可以结合示例看一下自己获取的信息是否正确,是否有遗漏

        4.尝试编写代码:

                (1)递归配组合,动态规划和滑动窗口来检验(会超时)

                        直接看代码吧,跟28题的解法差不多,只不过多了个递归而已

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int>res;
        string str;
        int size=words.size();
        GetRes(res,str,size,0,s,words);
        return res;
    }
private:
    void GetRes(vector<int>&res,string str,int size,int now,string&s,vector<string>words){
        if(now==size){
            int begin=0,end=str.size()-1;
            while(end<s.size()&&begin<=end){
                if(str[0]==s[begin]&&str[str.size()-1]==s[end])rever(s,str,begin,end,res);
                begin++;end++;
            }
            return;
        }
        for(int i=0;i<size;i++){
            if(words[i]=="")continue;
            string temp=str;
            temp+=words[i];
            string UH=words[i];
            words[i]="";
            GetRes(res,temp,size,now+1,s,words);
            words[i]=UH;
        }
    }
    void rever(string&s,string str,int begin,int end,vector<int>&res){
        int head=0,tail=str.size()-1;
        int UH=begin;
        while(head<=tail){
            if(str[head]!=s[begin]||str[tail]!=s[end])return;
            begin++;end--;head++;tail--;
        }
        if(find(res.begin(),res.end(),UH)==res.end()){
            res.push_back(UH);
        }
    }
};

        (2)尝试打算牺牲一下空间复杂度来拯救一下时间复杂度(会超时)

                如方法名字所言,就是这么个优化思路

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int>res;
        vector<string>table;
        string str;
        int size=words.size();
        GetRes(res,str,size,0,s,words,table);
        int border=table.size();
        int UH=s.size();
        for(int i=0;i<border;i++){
            int begin=0,end=table[i].size()-1;
            while(end<UH&&begin<=end){
                if(s[begin]==table[i][0]&&s[end]==table[i][table[i].size()-1])rever(s,table[i],begin,end,res);
                begin++;end++;
            }
        }
        return res;
    }
private:
    void GetRes(vector<int>&res,string str,int size,int now,string&s,vector<string>words,vector<string>&table){
        if(now==size){
            if(find(table.begin(),table.end(),str)==table.end())table.push_back(str);
            return;
        }
        for(int i=0;i<size;i++){
            if(words[i]=="")continue;
            string temp=str;
            temp+=words[i];
            string UH=words[i];
            words[i]="";
            GetRes(res,temp,size,now+1,s,words,table);
            words[i]=UH;
        }
    }
    void rever(string&s,string str,int begin,int end,vector<int>&res){
        int head=0,tail=str.size()-1;
        int UH=begin;
        while(head<=tail){
            if(str[head]!=s[begin]||str[tail]!=s[end])return;
            begin++;end--;head++;tail--;
        }
        res.push_back(UH);
    }
};

        (3)另辟蹊径法(会超时)

                上面的方法,我尽可能优化过了,没办法,只好推倒重来了

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int>res;
        int cap=words[0].size();
        int size=words.size()*cap;
        for(int i=0;i<s.size();i++){
            int end=i+size-1;
            if(end<s.size()&&GetRes(s,i,end,cap,words))res.push_back(i);
        }
        return res;
    }
private:
    bool GetRes(string&s,int begin,int end,int cap,vector<string>words){
        while(begin<=end){
            string str=s.substr(begin,cap);
            int i=0;
            for(i;i<words.size();i++){
                if(words[i]==str){
                    words[i]="";
                    i=-1;break;
                }
            }
            if(i!=-1)return false;
            begin+=cap;
        }
        return true;
    }
};

        (4)处理了明显不是起始位置的位置(会超时)

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        unordered_map<char,bool>head;
        unordered_map<string,int>hash;
        vector<int>res;
        for(string&word:words){
            head[word[0]]=true;
            hash[word]++;
        }
        int cap=words[0].size();
        int room=cap*words.size();
        int border=s.size();
        for(int i=0;i<border;i++){
            int end=i+room-1;
            if(end<border&&head.find(s[i])!=head.end()&&Check(s,i,end,hash,cap))res.push_back(i);
        }
        return res;
    }
private:
    bool Check(string&s,int begin,int end,unordered_map<string,int> hash,int cap){
        while(begin<=end){
            string str=s.substr(begin,cap);
            hash[str];
            if(hash[str]==0)return false;
            hash[str]--;
            begin+=cap;
        }
        return true;
    }
};

                这是对上述方法的优化

        (5)绞尽脑汁修改了一下(超时)

                我尽力又再次修改了一下,但还是不过

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        unordered_map<char,bool>head;
        unordered_map<string,int>hash;
        vector<int>res;
        for(string&word:words){
            head[word[0]]=true;
            hash[word]++;
        }
        int cap=words[0].size();
        int room=cap*words.size();
        int border=s.size();
        if(room>border)return res;
        for(int i=0;i<=border-room;i++){
            if(head.find(s[i])!=head.end()&&Check(s,i,i+room-1,hash,cap))res.push_back(i);
        }
        return res;
    }
private:
    bool Check(string&s,int begin,int end,unordered_map<string,int> hash,int cap){
        while(begin<=end){
            string str=s.substr(begin,cap);
            hash[str];
            if(hash[str]==0)return false;
            hash[str]--;
            begin+=cap;
        }
        return true;
    }
};

        (6)推倒重来吧(已经是我认为我能写出来的最极致的方法了,但还是超时了)

                重新换了个思路,发现还是不行,现阶段我应该是写不出来了,放到以后吧

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        unordered_map<char,bool>head;
        vector<int>res;
        int cap=words[0].size();
        int room=cap*words.size();
        int border=s.size();
        if (room>border)return res;
        for(string&word:words)head[word[0]]=true;
        unordered_map<string,int>wordCount;
        for(string&word:words)wordCount[word]++;
        for(int i=0;i<=border-room;i++) {
            if(!head.count(s[i]))continue;
            unordered_map<string,int>temp;
            for(int j=i;j<i+room;j+=cap){
                string str=s.substr(j,cap);
                if(!head.count(str[0]))break;
                temp[str]++;
            }
            if(temp==wordCount)res.push_back(i);
        }
        return res;
    }
};

这次的题解,看看就行了,毕竟我写的代码哪个都没通过,还是有点丢人的,你可以参考一下我这种优化,优化不行就换思路的方法和不服输的精神,坚持不懈的毅力嘛

等以后再重写这道题吧,暂时放弃了

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值