题目
给定两个字符串 s 和 p,找到 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
s 和 p 仅包含小写字母
实现代码
和【力扣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扫了一遍s2,right扫了一遍s2,那就是2*s,加上s1、s2所有字符集,最大26,去除常数最终的时间复杂度是O(N)
空间复杂度
额外空间left、right和两个数组,left和right的空间复杂度是O(1)可以不计,因为数组是存放字符次数的,大小取决于s1和s2不同字符的个数,最大也就26,所以去除常数的空间复杂度为O(1)