题目

给定两个字符串 sp,找到 s 中所有 p异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

示例 1:

1
2
3
4
5
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

示例 2:

1
2
3
4
5
6
输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

提示:

  • 1 <= s.length, p.length <= 3 * 104
  • sp 仅包含小写字母

实现代码

【力扣76】最小覆盖字串思路一样,使用双指针的滑动窗口来实现

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
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public List<Integer> findAnagrams(String s, String p) {
int left = 0, right = 0, sLen = s.length(), pLen = p.length(), n = 0, pn = 0;
int[] windowCount = new int[26];
int[] pCount = new int[26];
for (char c : p.toCharArray()) {
if (pCount[c - 'a'] == 0) {
pn++;
}
pCount[c - 'a']++;
}
List<Integer> countList = new ArrayList<>();
while (right < sLen) {
int c = s.charAt(right);
right++;
if (pCount[c - 'a'] > 0) {
windowCount[c - 'a']++;
if (pCount[c - 'a'] == windowCount[c - 'a']) {
n++;
}
}
while (n == pn) {
if ((right - left) == pLen) {
// 符合条件添加到集合
countList.add(left);
}
char c1 = s.charAt(left);
left++;
if (windowCount[c1 - 'a'] > 0) {
if (windowCount[c1 - 'a'] == pCount[c1 - 'a']) {
n--;
}
windowCount[c1 - 'a']--;
}
}
}
return countList;
}
}

时间复杂度

最差的情况是left扫了一遍s2right扫了一遍s2,那就是2*s,加上s1s2所有字符集,最大26,去除常数最终的时间复杂度是O(N)

空间复杂度

额外空间leftright和两个数组,leftright的空间复杂度是O(1)可以不计,因为数组是存放字符次数的,大小取决于s1s2不同字符的个数,最大也就26,所以去除常数的空间复杂度为O(1)