05 August 2008
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.
Example 1:
1
2
3
4
5
6
Input:
s = "barfoothefoobarman",
words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:
1
2
3
4
Input:
s = "wordgoodstudentgoodword",
words = ["word","student"]
Output: []
这道题跟上一道题76 Minimum Window Substring的找子字符串的方法类似。给定一个目标字符串s,一个单词集合words。 要求使得words集合中所有元素连续出现在s中的首位置组成的集合(元素顺序不考虑)。
正如所给实例,目标字符串s: “barfoothefoobarman” 对比单词集合words: [“foo”, “bar”] 我们发现,在pos=0 ~ 5时“barfoo”恰好匹配,则0存入结果;在pos=9 ~ 14时“foobar”恰好匹配,则9存入结果;
参考了discuss的解法,利用两个map,一个来记录每个单词的次数,另一个来记录看到的次数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new ArrayList<>();
if (words.length == 0) {
return res;
}
Map<String, Integer> dict = new HashMap<>();
Map<String, Integer> found = new HashMap<>();
for (String word : words) {
dict.put(word, dict.getOrDefault(word, 0) + 1);
}
int wordLen = words[0].length(), totalLen = words.length * wordLen, strLen = s.length();
for (int start = 0; start < strLen - totalLen + 1; start++) {
int end = start;
while (end < start + totalLen) {
String substr = s.substring(end, end + wordLen);
found.put(substr, found.getOrDefault(substr, 0) + 1);
if (found.get(substr) > dict.getOrDefault(substr, 0)) { break; }
end += wordLen;
}
if (end == start + totalLen) { res.add(start); }
found.clear();
}
return res;
}
}