用java实现。 给定一个字符串 str 和一个字符串数组 words。 words 中所有字符串长度相同。 str 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如,如果 words = ["ab","cd","ef"], 那么 "abcdef", "abefcd","cdabef", "cdefab","efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。 请找到所有串联字符串在 str 中的开始索引,最终结果以int数组形式,索引按照从小大到的顺序返回。
时间: 2023-07-08 21:43:23 浏览: 166
Day05_剑指Offer.md
好的,这是一个字符串处理的问题,我会尽力帮你解决。以下是Java实现的代码:
```java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Solution {
public int[] findSubstring(String str, String[] words) {
if (str == null || str.length() == 0 || words == null || words.length == 0) {
return new int[0];
}
int n = str.length();
int m = words.length;
int len = words[0].length();
if (n < m * len) {
return new int[0];
}
Map<String, Integer> freq = new HashMap<>(); // 统计每个单词的出现次数
for (String word : words) {
freq.put(word, freq.getOrDefault(word, 0) + 1);
}
List<Integer> res = new ArrayList<>(); // 存储结果
for (int i = 0; i <= n - m * len; i++) {
Map<String, Integer> seen = new HashMap<>(); // 统计当前窗口内每个单词的出现次数
int j = 0;
while (j < m) {
String word = str.substring(i + j * len, i + (j + 1) * len);
if (freq.containsKey(word)) {
seen.put(word, seen.getOrDefault(word, 0) + 1);
if (seen.get(word) > freq.get(word)) { // 如果窗口内某个单词的出现次数超过了其在 words 中的出现次数,则窗口无效
break;
}
} else { // 如果窗口内出现了不在 words 中的单词,则窗口无效
break;
}
j++;
}
if (j == m) { // 如果窗口内的单词已经包含了 words 中的所有单词,则窗口有效
res.add(i);
}
}
int[] ans = new int[res.size()];
for (int i = 0; i < res.size(); i++) {
ans[i] = res.get(i);
}
return ans;
}
}
```
这个算法的时间复杂度是 $O(nm)$,其中 $n$ 是字符串的长度,$m$ 是单词数组中单词的个数。如果单词的长度是固定的,也就是题目中说的“所有字符串长度相同”,那么算法的时间复杂度就是 $O(n)$。
阅读全文