.
题目链接
题目详情
题目解析
这里可以参考找到字符串中所有的字母异位词这道题,但是,一个是异位词,一个是异位串
,将words中的字符串看出一个个的单词,就可以采用一样的思路来解决这个问题
需要注意的是:
- 这里不能采用数组来模拟容器,而只能使用向List<String,Integer>这样的链表来记录字符串的个数
- left和right一次性需要跳过的字节长度,是根据words中每个单词的长度来的
- 这道题我们依旧采用滑动窗口来解决问题,但是滑动窗口执行的次数却需要做出改变:
如图,滑动窗口的执行次数,也是根据words中每个单词的长度来的,且每次left与right开始遍历的位置也会相对发生偏移
算法原理
滑动窗口流程图
定义变量
双指针的初始值与滑动窗口的次数相同
每一次滑动窗口都需要不同的hash2,因此定义它的位置需要额外注意
创建变量count来记录有效字符串个数
进窗口
- 将right所在位置的字符串存到hash2中
- 维护有效字符串个数count
判断
判断窗口内字符串总长度是否超过words的所有字符串之和
出窗口
将left所在字符串移除hash2,在移除之前维护有效字符串个数count
更新结果
如果count与words的字符串个数相同,则满足条件,将当前窗口的left下标加入到返回链表中
我的答案
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
//创建返回值
List<Integer> list = new ArrayList<Integer>();
//创建hash1,存储words的字符串
Map<String,Integer>hash1 = new HashMap<String,Integer>();
for(String ss:words){
hash1.put(ss,hash1.getOrDefault(ss,0)+1);
}
//滑动次数
int wordLen = words[0].length(),size = words.length;
for(int i = 0;i<wordLen;i++){
//定义指针变量
//创建hash2,存储窗口中的字符串
Map<String,Integer>hash2 = new HashMap<String,Integer>();
for(int left = i,right = i,count=0;right+wordLen<=s.length();right+=wordLen){
//进窗口
String in = s.substring(right,right+wordLen);
hash2.put(in,hash2.getOrDefault(in,0)+1);
//维护有效字符串
if(hash2.get(in)<=hash1.getOrDefault(in,0))//hash1可能没有该值
count++;
//判断
if(right-left+1>size*wordLen){
//出窗口
String out = s.substring(left,left+wordLen);
//维护有效字符串个数
if(hash2.get(out)<=hash1.getOrDefault(out,0))
count--;
hash2.put(out,hash2.get(out)-1);
left+=wordLen;
}
//更新结果
if(count==words.length)
list.add(left);
}
}
return list;
}
}