30. Substring with Concatenation of All Words(串联所有单词的子串)

方法一:

    两个 HashMap 来解决。首先,我们把所有的单词存到 HashMap 里,key 直接存单词,value 存单词出现的个数(。然后扫描子串的单词,如果当前扫描的单词在之前的 HashMap 中,就把该单词存到新的 HashMap 中,并判断新的 HashMap 中该单词的 value 是不是大于之前的 HashMap 该单词的 value ,如果大了,就代表该子串不是我们要找的,接着判断下一个子串就可以了。如果不大于,那么我们接着判断下一个单词的情况。子串扫描结束,如果子串的全部单词都符合,那么该子串就是我们找的其中一个。看下具体的例子。

看下图,我们把 words 存到一个 HashMap 中。

然后遍历子串的每个单词。

第一个单词在 HashMap1 中,然后我们把 foo 存到 HashMap2 中。并且比较此时 foo 的 value 和 HashMap1 中 foo 的 value,1 < 2,所以我们继续扫描。

第二个单词也在 HashMap1 中,然后把 foo 存到 HashMap2 中,因为之前已经存过了,所以更新它的 value 为 2 ,然后继续比较此时 foo 的 value 和 HashMap1 中 foo 的 value,2 <= 2,所以继续扫描下一个单词。

第三个单词也在 HashMap1 中,然后把 foo 存到 HashMap2 中,因为之前已经存过了,所以更新它的 value 为 3,然后继续比较此时 foo 的 value 和 HashMap1 中 foo 的 value,3 > 2,所以表明该字符串不符合。然后判断下个子串就好了。

下面是AC代码,87ms.

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> list=new ArrayList();
        if(s==null||s.length()==0||words==null||words.length==0)
            return list;
        Map<String,Integer> wordMap=new HashMap();
        for(String word : words){
            if(!wordMap.containsKey(word))
                wordMap.put(word,1);
            else
                wordMap.put(word,wordMap.get(word)+1);
        }
        int slen=s.length(),arraylen=words.length,wordlen=words[0].length();
        for(int i=0;i<slen-arraylen*wordlen+1;i++){
            Map<String,Integer> map=new HashMap();
            int num=0;
            while(num<arraylen){
                String word=s.substring(i+num*wordlen,i+(num+1)*wordlen);
                if(wordMap.containsKey(word)){
                    int value=map.getOrDefault(word,0);
                    map.put(word,value+1);
                    if(wordMap.get(word)<map.get(word))
                        break;
                }else
                    break;
                num++;
            }
            if(num==arraylen)
                list.add(i);
        }
        return list;
    }
    
}

方法二:

对上面的解法进行优化,同样用两个HashMap存储,这个优化方案是利用了给定的Word都是等长的

虽然该方案不具备普适性,但是对于这道题来说,这个优化是可行的,可以提高效率。

具体做法是,循环利用原来的匹配结果来跳过那些没必要匹配的值。

优化难点在于对三种情形下left值以及map和num值的更新。

详细理解:详细图解

AC代码如下: 13ms beats 96.6%

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        List<Integer> list=new ArrayList();
        if(s==null||s.length()==0||words==null||words.length==0)
            return list;
        Map<String,Integer> wordMap=new HashMap();
        for(String word : words){
            if(!wordMap.containsKey(word))
                wordMap.put(word,1);
            else
                wordMap.put(word,wordMap.get(word)+1);
        }
        int slen=s.length(),arraylen=words.length,wordlen=words[0].length();
        for(int i=0;i<wordlen;i++){
            Map<String,Integer> map=new HashMap();
            int num=0;
            for(int left=i;left<slen-arraylen*wordlen+1;left=left+wordlen){
                boolean remove=false;
                while(num<arraylen){
                    String word=s.substring(left+num*wordlen,left+(num+1)*wordlen);
                    if(wordMap.containsKey(word)){
                        int value=map.getOrDefault(word,0);
                        map.put(word,value+1);
                        if(map.get(word)>wordMap.get(word)){
                            remove=true;
                            int count=0;
                            while(map.get(word)>wordMap.get(word)){
                                String more=s.substring(left+count*wordlen,left+(count+1)*wordlen);
                                map.put(more,map.get(more)-1);
                                count++;
                            }
                            num=num-count+1;
                            left=left+(count-1)*wordlen;
                            break;
                        }
                    }else{
                        map.clear();
                        left=left+num*wordlen;
                        num=0;
                        break;
                    }
                    num++;
                }
                if(num==arraylen)
                    list.add(left);
                if(num==arraylen&&!remove){
                    String w=s.substring(left,left+wordlen);
                    map.put(w,map.get(w)-1);
                    num--;
                }
            }       
        }
        return list;
    }
    
}

致谢参考: 链接

猜你喜欢

转载自blog.csdn.net/God_Mood/article/details/87611209
今日推荐