算法之难,难于上青天,别拦我,我要上天
给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
示例 1:
输入:
s = "barfoothefoobarman",
words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:
输入:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
输出:[]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
目前还没有发现比滑动窗口解这道题更好的方法
滑动窗口,第一次遇见是在计算机网络中
图解
其中运用到了getOrDefault()方法,判断map是否含有key,含有的话就是返回当前key对应的值,否则返回自己设定的默认值。
@Override public V getOrDefault(Object key, V defaultValue) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? defaultValue : e.value; }
解题代码
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
//存储结果的链表
List<Integer> ans = new ArrayList<>();
//获取字符创的长度
int sLen = s.length();
//获取单词数组的长度,也就是单词的个数
int wordNum = words.length;
if(wordNum == 0){
return ans;
}
//获取单词的长度
int wordLen = words[0].length();
//设置窗口的长度
int windowLen = wordLen * wordNum;
HashMap<String, Integer> wordCount = new HashMap<String, Integer>();
//把单词以及其个数存在hashMap中
for(String word : words){
//运用HashMap函数
int val = wordCount.getOrDefault(word,0);
wordCount.put(word,val+1);
}
//在字符串中进行窗口滑动找到符合题目的index
for(int i = 0 ; i < sLen - windowLen + 1 ; i++){
//用于窗口单词计数
int count = 0;
//存储窗口中单词及出现次数
HashMap<String, Integer> windowWord = new HashMap<>();
while(count < wordNum){
String word = s.substring(i + count * wordLen,i + (count + 1) * wordLen);
if(wordCount.containsKey(word)){
int val = windowWord.getOrDefault(word,0);
windowWord.put(word,val + 1);
if(windowWord.get(word) > wordCount.get(word)){
break;
}
}else {
break;
}
count++;
}
if(count == wordNum){
ans.add(i);
}
}
return ans;
}
}