Substring with Concatenation of All Words (H)
题目
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:
Input:
s = "barfoothefoobarman",
words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoo" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:
Input:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
Output: []
题意
给定一个字符串s和单词数组words,判断s中是否存在一个子串,正好为words中所有单词连起来的字符串(顺序不计)。
思路
暴力法:直接将每个单词看做是一个字符进行匹配,因为单词的顺序不一定,可以用HashMap来记录单词和出现次数的对应关系。
\(O(N)\)优化:暴力法的缺陷在于进行了大量的重复计算。参考 LeetCode 30. Substring with Concatenation of All Words 进行优化。
代码实现
Java
暴力
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
if (words.length == 0) {
return new ArrayList<>();
}
int len = words[0].length(), num = words.length;
List<Integer> list = new ArrayList<>();
Map<String, Integer> record = new HashMap<>();
Map<String, Integer> tmp = new HashMap<>();
for (String word : words) {
record.putIfAbsent(word, 0);
record.put(word, record.get(word) + 1);
}
for (int i = 0; i < s.length(); i++) {
if (s.length() - i < num * len) {
break;
}
tmp.clear();
int j = i;
while (j - i != num * len) {
String w = s.substring(j, j + len);
if (!record.containsKey(w)) {
break;
}
tmp.putIfAbsent(w, 0);
tmp.put(w, tmp.get(w) + 1);
if (tmp.get(w) > record.get(w)) {
break;
}
j += len;
}
if (j - i == num * len) {
list.add(i);
}
}
return list;
}
}
\(O(N)\)优化
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
if (words.length == 0) {
return new ArrayList<>();
}
int len = words[0].length(), num = words.length;
List<Integer> list = new ArrayList<>();
Map<String, Integer> record = new HashMap<>();
Map<String, Integer> tmp = new HashMap<>();
for (String word : words) {
record.putIfAbsent(word, 0);
record.put(word, record.get(word) + 1);
}
for (int i = 0; i < len && i < s.length(); i++) {
if (s.length() - i < num * len) {
break;
}
tmp.clear();
int left = i, right = i;
while (true) {
if (right - left == num * len) {
list.add(left);
String headW = s.substring(left, left + len);
tmp.put(headW, record.get(headW) - 1);
left += len;
}
if (s.length() - left < num * len) {
break;
}
String w = s.substring(right, right + len);
if (!record.containsKey(w)) {
tmp.clear();
left = right + len;
} else {
tmp.putIfAbsent(w, 0);
tmp.put(w, tmp.get(w) + 1);
while (tmp.get(w) > record.get(w) && s.length() - left >= num * len) {
String headW = s.substring(left, left + len);
tmp.put(headW, tmp.get(headW) - 1);
left += len;
}
}
right += len;
}
}
return list;
}
}