You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in wordsexactly once and without any intervening characters.
同样可以采用滑动窗口法解决。在移动的过程中维护一个HashMap的字典,保存查找的字符串状况。
step 1.构建一个HashMap dict的字典,key-value对应words中的word和出现的次数。注意给定的words中可能多次出现同一个word。
step 2.设word的length为wLen(每个word的长度都相同),第一层循环wLen次,每次循环整个字符串。
step 3.第二层循环每次循环前进wLen位,遍历整个字符串,单次循环内次数为s.length()/wLen。这样两层循环就可以覆盖所有可能的字符串。用startIndex记录匹配字符串的开始位置,count记录匹配的字典字符串的个数。用另一个HashMap curMap维护当前匹配字符串中字典字符串的状况。通过比较dict和curMap的key-value来更新count和startIndex。注意:当前匹配的字典字符串在整个匹配字符串中出现的次数超出即curMap.get(sub) > dict.get(sub),那么startIndex应直接移动到该匹配的字典字符串后一次出现位置之后,count同样减小。
packagecom.samxcode.leetcode; importjava.util.ArrayList; importjava.util.HashMap; importjava.util.List; /** * You are given a string, s, and a list of words, words, that are all of the same length. Find all * starting indices of substring(s) in s that is a concatenation of each word in words exactly once * and without any intervening characters. * * @author Sam * */ publicclassFindSubstring { publicstaticvoidmain(String[] args) { String[] words = {"a","b","a"}; System.out.println(findSubstring("abababab", words)); } publicstaticList<Integer> findSubstring(String s, String[] words) { List<Integer> res =newArrayList<Integer>(); if(words.length ==0|| s.length() ==0) { returnres; } intwLen = words[0].length(); // the count of special words displayed each loop intcount; // the start index each matching process intstartIndex; // put the given dictionary into hash map with each word's count HashMap<String, Integer> dict =newHashMap<String, Integer>(); // dictionary in current matching process HashMap<String, Integer> curMap =newHashMap<String, Integer>(); for(String word : words) { if(dict.containsKey(word)) dict.put(word, dict.get(word) +1); else dict.put(word,1); } for(inti =0; i < wLen; i++) { count =0; startIndex = i; curMap.clear(); for(intj = i; j <= s.length() - wLen; j += wLen) { // current word String sub = s.substring(j, j + wLen); if(dict.containsKey(sub)) { // update current dictionary if(curMap.containsKey(sub)) curMap.put(sub, curMap.get(sub) +1); else curMap.put(sub,1); count++; // check if count for current found word exceed given word count if(curMap.get(sub) > dict.get(sub)) { // shift the start index to the found word's next word and update the count while(curMap.get(sub) > dict.get(sub)) { String temp = s.substring(startIndex, startIndex + wLen); curMap.put(temp, curMap.get(temp) -1); startIndex += wLen; count--; } } // put the start index into result, shift index to next word, and update current // dictionary and count if(count == words.length) { res.add(startIndex); String temp = s.substring(startIndex, startIndex + wLen); curMap.put(temp, curMap.get(temp) -1); startIndex += wLen; count--; } }else{ curMap.clear(); startIndex = j + wLen; count =0; } } } returnres; } }
第一层循环wLen次,第二层循环n/wLen次,所以时间复杂度O(n),空间复杂度O(d*l),s 字典大小,l 字典字符串长度