原题链接在这里: https://leetcode.com/problems/substring-with-concatenation-of-all-words/description/
题目:
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.
For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]
You should return the indices: [0,9]
.
(order does not matter).
题解:
类似Longest Substring Without Repeating Characters, 这类快慢指针维护substring的方法在Minimum Window Substring里有总结.
需要先生成global map计算words中每个word 的frequency. 快慢指针围成的window里也有个小的map计算map中出现在words的word, 当出现一个就count++.
当count是words数目和时就找到了一个结果.
检查当前词是否是words里的词时外层循环是多种取词方法,以例子来说就是分成:
|bar|foo|the|foo|bar|man
b|arf|oot|hef|oob|arm|an
ba|rfo|oth|efo|oba|rma|n
Note: s.substring(startIndex, endIndex) 其中的endIndex必须比s string本身长度小.
Time Complexity: O(s.length()).
Space: O(words.length).
AC Java:
1 class Solution { 2 public List<Integer> findSubstring(String s, String[] words) { 3 List<Integer> res = new ArrayList<Integer>(); 4 if(words == null || words.length == 0 || s == null || s.length() == 0){ 5 return res; 6 } 7 8 // 计算原有word frequency 9 HashMap<String, Integer> hm = new HashMap<String, Integer>(); 10 for(String word : words){ 11 hm.put(word, hm.getOrDefault(word, 0)+1); 12 } 13 14 int wordLen = words[0].length(); 15 int count = 0; 16 int walker = 0; 17 18 // 从等长word长度的开始到结尾挨个试,不需要再往后,因为那已经被长度开始里面的runner下一跳包括 19 for(int i = 0; i<wordLen; i++){ 20 walker = i; 21 count = 0; 22 HashMap<String, Integer> windowHm = new HashMap<String, Integer>(); 23 int max = s.length()-wordLen+1; 24 25 for(int runner = walker; runner < max; runner += wordLen){ 26 String cur = s.substring(runner, runner+wordLen); 27 if(hm.containsKey(cur)){ 28 // cur string在words中 29 windowHm.put(cur, windowHm.getOrDefault(cur, 0)+1); 30 if(windowHm.get(cur) <= hm.get(cur)){ 31 count++; 32 }else{ 33 // cur这个词在window里出现的次数 多余 原来words中的次数 34 while(windowHm.get(cur) > hm.get(cur)){ 35 String walkerStr = s.substring(walker, walker+wordLen); 36 windowHm.put(walkerStr, windowHm.get(walkerStr)-1); 37 if(windowHm.get(walkerStr) < hm.get(walkerStr)){ 38 count--; 39 } 40 walker += wordLen; 41 } 42 } 43 44 // 全部覆盖,向前移动walker 45 if(count == words.length){ 46 res.add(walker); 47 String walkerStr = s.substring(walker, walker+wordLen); 48 windowHm.put(walkerStr, windowHm.get(walkerStr)-1); 49 count--; 50 walker += wordLen; 51 } 52 }else{ 53 // cur 不在words中 54 windowHm.clear(); 55 count = 0; 56 walker = runner+wordLen; 57 } 58 } 59 } 60 61 return res; 62 } 63 }