遍历所有words,将words中的每个字符串都存在
hashMap allwords中
,key
存放值,value
存放其出现的次数,遍历所有子串,将当前子串所包含单词存放hasWords
中,若遍历到的字符串不存在allwords
中的字符串,或者电气概念遍历到的字符串中的个数大于allWords
中的字符串则结束此次遍历接着下次遍历,在这种方式下,我们每次移动一个字符串
package KTwoPointers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* @Author Zhou jian
* @Date 2020 ${month} 2020/5/10 0010 12:15
*/
public class Problem30 {
/**
* 1、遍历words,将words中的每个字符串都存到hashMap allwords中,key存放值,value存放其出现的次数
* 2、遍历所有子串,将当前子串所含单词存放hasWords中,
* 若当前遍历到的字符串不存在allwords中的字符串,
* 或者当前遍历到的字符串中的个数大于allwords中的字符串则结束此次遍历接着下次遍历
* 在这种方法中 ,我们每次移动一个字符串
* @param s
* @param words
* @return
*/
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res=new ArrayList<>();
if (words==null||words.length==0)return res;
//单词个数、单词长度
int wordNum = words.length,wordLen=words[0].length();
//将words每个单词及其个数存入hashmap
HashMap<String,Integer> allWords=new HashMap<>();
//将待匹配字符串存入hashMap中
for (String word : words) {
Integer value = allWords.getOrDefault(word, 0);
allWords.put(word,++value);
}
//反言之:检查每个子串的过程中,出现words中的补存在的单词则结束检查
//出现与words中相等的单词,但是出现的次数超过其在words中出现的次数则结束检查
//遍历s每一个子串,剩余不足wordNum*wordLen个字符的子串不需要遍历
//时间复杂度:O(N*m)
for (int i = 0; i < s.length() - wordNum * wordLen + 1; i++) {
//将子串中出现的和words中相等的单词及其出现次数存入hashmap
HashMap<String,Integer> hasWords=new HashMap<>();
//记录字串中和words中相等单词数量
int count=0;
//统计字串中连续和words中相等的单词
while (count<wordNum){
//因为待比较的字符串中的长度都一样因此可以采用这种方式
String word = s.substring(i + count * wordLen, i + (count + 1) * wordLen);
//如果word匹配words中的单词,就统计其出现次数
if (allWords.containsKey(word)){
Integer value = hasWords.getOrDefault(word, 0);
hasWords.put(word,++value);
//如果word出现次数超过words中这个单词的总数量则结束统计
if (hasWords.get(word)>allWords.get(word))break;
}else {
//如果字串中出现于words中所有单词都不匹配的word则结束统计
break;
}
//增加成功与words中匹配的单词数量
count++;
}
if (count==wordNum)res.add(i);
}
return res;
}
}