题目:
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).
用HashMap简单粗暴比较。唯一的优化是当s中出现重复单词且超过在dict中的数量时,可以将指针向前移动到该重复单词的下一个单词处。
C++版:
class Solution { public: vector<int> findSubstring(string s, vector<string>& words) { int length = words[0].length() * words.size(); vector<int> results; if(s.length() < length) return results; unordered_map<string, int> occurrences; for(int i = 0; i < words.size(); i++) { if(occurrences.find(words[i]) == occurrences.end()) occurrences.insert(pair<string, int>(words[i], 1)); else occurrences[words[i]]++; } for(int i = 0; i <= s.length() - length; i++) { string temp = s.substr(i, length); test(results, occurrences, temp, (int)words[0].length(), (int)words.size(), i); } return results; } void test(vector<int>& results, unordered_map<string, int> occurrences, string& s, int l, int n, int& pos) { for(int i = 0; i < n; i++) { string current = s.substr(i * l, l); if(occurrences.find(current) != occurrences.end()) { if(occurrences[current] > 0) occurrences[current]--; else { pos = pos + s.find(current) + l - 1; return; } } else { return; } } results.push_back(pos); } };
public class Solution { public List<Integer> findSubstring(String s, String[] words) { List<Integer> results = new ArrayList<Integer>(); if(words.length * words[0].length() > s.length()) return results; Map<String, Integer> count = new HashMap<>(); for(int i = 0; i < words.length; i++) { if(count.containsKey(words[i])) count.put(words[i], count.get(words[i]) + 1); else count.put(words[i], 1); } for(int i = 0; i <= s.length() - words.length * words[0].length(); i++) { Map<String, Integer> local = new HashMap<String, Integer>(count); int j; for(j = 0; j < words.length; j++) { String current = s.substring(i + j * words[0].length(), i + (j + 1) * words[0].length()); if(local.containsKey(current)) { if(local.get(current) > 0) local.put(current, local.get(current) - 1); else { i = s.indexOf(current, i) + words[0].length() - 1; break; } } else { break; } } if(j == words.length) results.add(i); } return results; } }
import copy class Solution: # @param {string} s # @param {string[]} words # @return {integer[]} def findSubstring(self, s, words): results = [] if len(s) < len(words) * len(words[0]): return results count = {} for i in words: if i in count: count[i] += 1 else: count[i] = 1 i = 0 while i <= len(s) - len(words) * len(words[0]): local = copy.copy(count) j = 0 while j < len(words): current = s[i + j * len(words[0]) : i + (j + 1) * len(words[0])] if current in local: if local[current] > 0: local[current] -= 1 j += 1 else: i = s.find(current, i) + len(words[0]) - 1 break else: break if j == len(words): results.append(i) i += 1 return results