串联所有单词的子串

如上图,利用循环变量 i ,依次后移,判断每个子串是否符合即可。

怎么判断子串是否符合?这也是这个题的难点了,由于子串包含的单词顺序并不需要固定,如果是两个单词 A,B,我们只需要判断子串是否是 AB 或者 BA 即可。如果是三个单词 A,B,C 也还好,只需要判断子串是否是 ABC,或者 ACB,BAC,BCA,CAB,CBA 就可以了,但如果更多单词呢?那就崩溃了。

用两个 HashMap 来解决。首先,我们把所有的单词存到 HashMap 里,key 直接存单词,value 存单词出现的个数(因为给出的单词可能会有重复的,所以可能是 1 或 2 或者其他)。然后扫描子串的单词,如果当前扫描的单词在之前的 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,所以表明该字符串不符合。然后判断下个子串就好了。

当然上边的情况都是单词在 HashMap1 中,如果不在的话就更好说了,不在就表明当前子串肯定不符合了,直接判断下个子串就好了。

#java

public List findSubstring(String s, String[] words) {

    List res = new ArrayList();

    int wordNum = words.length;

    if (wordNum == 0) {

        return res;

    }

    int wordLen = words[0].length();

//第一个单词的长度

    //HashMap1 存所有单词

    HashMap allWords = new HashMap();

    for (String w : words) {

        int value = allWords.getOrDefault(w, 0);

        allWords.put(w, value + 1);

    }

    //遍历所有子串

    for (int i = 0; i < s.length() - wordNum * wordLen + 1; i++) {

        //HashMap2 存当前扫描的字符串含有的单词

        HashMap hasWords = new HashMap();

        int num = 0;

        //判断该子串是否符合

        while (num < wordNum) {

            String word = s.substring(i + num * wordLen, i + (num + 1) * wordLen);

            //wordNum词的个数(0,wordLen),wordLen为第一个词的长度

          //第二个是i=0,(wordLen,2*wordLen),这是因为每个词语的长度相同,通过首位置+第几个*长度来进行滑动窗口

          //从句子中获得分割的词汇

            //判断该单词在 HashMap1 中

            if (allWords.containsKey(word)) {

                int value = hasWords.getOrDefault(word, 0);

//获得该词汇在表中之前的个数,包含就统计

      hasWords.put(word, value + 1);

//哈希表的统计--表.put(word,value+1)

                //判断当前单词的 value 和 HashMap1 中该单词的 value,两个对应词汇进行比较,相同就是

                if (hasWords.get(word) > allWords.get(word)) {

                    break;

                }

            } else {

                break;

            }

            num++;

//统计匹配的个数

        }

        //判断是不是所有的单词都符合条件

        if (num == wordNum) {

//全部匹配则符合,则把匹配的首位置输出,i用来设置词被截断的首位置,在这里是将所有匹配的首位置全部输出

            res.add(i);

        }

    }

    return res;

}

#首位置分割--(利用i+num*wordLen)---#包含统计----比较匹配---匹配成功则记录首位置

你可能感兴趣的:(串联所有单词的子串)