class Solution {
//我们使用滑动窗口来解决这个字符串匹配问题
public static List<Integer> findSubstring(String s, String[] words) {
//使用res来接收最后结果
ArrayList<Integer> res = new ArrayList<>();
//1. 统计words数组中每个单词出现的次数,使用map来进行存储
HashMap<String, Integer> wordMap = new HashMap<>();
for (String str : words) {
if (wordMap.containsKey(str)) {
wordMap.put(str, wordMap.get(str) + 1);
} else {
//如果map中不存在,则直接加入
wordMap.put(str, 1);
}
}
//2. 找出窗口的大小
int wordLen = words[0].length();
//因为每个单词的长度是相等的故,不管他有没有重复,我们直接使用每个单词的长度*单词的数量
//得到窗口的大小
int len = wordLen * words.length;
//3. 开始匹配,这里要注意我们的循环长度,因为我们已经是从一个窗口开始匹配,那么他循环的次数等于当前
//主串的总长-窗口长+1次
for (int i = 0; i < s.length() - len + 1; i++) {
//开始取窗口大小的子串
String s1 = s.substring(i, i + len);
//新建一个map用来统计当前s1中串中每个单词大小的串的出现次数,如果出现的次数等于前面统计的
//wordMap中统计的次数,那门他们绝逼相等
//下面使用另一种,就是我们把前面拿到的hashmap放入到这个临时的map中,此时tmpmap中记录了
//words中每个单词出现的次数,我们只需要遍历当前串,将遍历到的单词在临时map中将其次数减少即可,最后,
//我们判断临时map是否为空,如果为空,则表示完全匹配
HashMap<String, Integer> tmpMap = new HashMap<>(wordMap);
//遍历这个取出的子串,这里我们规定遍历每次走一个单词长度
for (int j = 0; j < s1.length(); j += wordLen) {
String word = s1.substring(j, j + wordLen);
if (tmpMap.containsKey(word)) {
tmpMap.put(word, tmpMap.get(word) - 1);
if (tmpMap.get(word) == 0) {
//移除当前哈希表中的元素,这里要进行移除,当我们map减少至0时,此时map中还是存在这个word的,话句话说就是他还会去继续匹配
//那么,他就永远不会有与子串匹配的,故要移除。
tmpMap.remove(word);
}
} else {
//不包含的话肯定不匹配,直接跳出循环即可
break;
}
}
//内层循环结束
if (tmpMap.size() == 0) {
//完全匹配
res.add(i);
}
}
return res;
}
}
leetcode30--滑动窗口系列
最新推荐文章于 2023-03-21 15:05:13 发布