串联所有单词的子串. - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/substring-with-concatenation-of-all-words/
如果是第一次接触这个题目,接触滑动窗口的题目,那么这个题目则非常困难。但是经过我我们之前几个题的滑动窗口的磨炼,这个题只是在上一个题目的基础上变难了一些,细节变多了一些。
首先,题目的要求是返回符合要求的下标:
并且要注意的是,和右边的数组里面的元素相同才符合题意,如果只有一个foo或者一个bar,则不满足要求。
既然以3个字母为一组,那么我们就可以简化成这样:
把三个字符看成一个整体,left和right指针也是进行整体的加减。如此会出现一个问题,如果符合题目要求的字符,是从第二个,第三个字母开始的呢?
我们就循环几次,第一次把abb作为一个整体,第二次把bba作为一个整体,第三次把bar作为一个整体,并且只需要几次就可以全部覆盖到,这个次数和words里面的元素的长度有关。
在这个循环里面,就变成了跟上一个题目一样了,也是进窗口,维护count,出窗口,维护count
要注意的是,right和left的起始位置,跟上一层循环有关,right和left向右移动的长度,和words里面的元素的长度有关。
代码:
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> ret = new ArrayList<Integer>();
Map<String, Integer> hash1 = new HashMap<String, Integer>();
for(String str: words){
hash1.put(str, hash1.getOrDefault(str,0) + 1);
}
int len = words[0].length();
int m = words.length;
for(int i = 0; i < len; i++){
Map<String, Integer> hash2 = new HashMap<String, Integer>();
for(int left = i, right = i, count = 0; right + len <= s.length(); right += len){
String in = s.substring(right, right + len);
hash2.put(in, hash2.getOrDefault(in, 0) + 1);
if(hash2.get(in) <= hash1.getOrDefault(in, 0)){
count++;
}
if(right - left + 1 > len * m){
String out = s.substring(left, left + len);
if(hash2.get(out) <= hash1.getOrDefault(out, 0)){
count--;
}
hash2.put(out, hash2.get(out) - 1);
left += len;
}
if(count == m){
ret.add(left);
}
}
}
return ret;
}
}