1.题目描述:
给定两个字符串s和p,找到s中所有p的异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。异位词指由相同字母重排列形成的字符串(包括相同的字符串)。
2. 基于leetcode242. 有效的字母异位词的暴力解法:
class Solution {
public List<Integer> findAnagrams(String s, String p) {
if (s.length() < p.length()) return new ArrayList();
int len = p.length();
int[] arr = new int[26];
List<Integer> list = new ArrayList<>();
for (int i = 0; i < len; i++) {//计数字符串p
arr[p.charAt(i) - 'a']++;
}
for (int i = 0; i < s.length() - len + 1; i++) {
for (int j = i; j < i + len; j++) {
arr[s.charAt(j) - 'a']--;
}
boolean flag = true;//需要重置
for (int j = 0; j < arr.length; j++) {
if (arr[j] != 0) {
flag = false;
break;
}
}
if (flag) list.add(i);
for (int j = i; j < i + len; j++) {//重置arr
arr[s.charAt(j) - 'a']++;
}
}
return list;
}
}
3.双指针/滑动窗口:
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> list = new ArrayList<>();
int m = p.length();
int n = s.length();
int[] arr1 = new int[26];
int[] arr2 = new int[26];
for (int i = 0; i < m; i++) {
arr2[p.charAt(i) - 'a']++;
}
for (int l = 0, r = 0; r < n; r++) {
arr1[s.charAt(r) - 'a']++;
if (r - l + 1 > m) arr1[s.charAt(l++) - 'a']--;//滑动窗口
if (Arrays.equals(arr1, arr2)) list.add(l);
}
return list;
}
}
4.双指针/滑动窗口继续优化:只用一个计数数组arr。
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> list = new ArrayList<>();
int m = p.length();
int n = s.length();
int[] arr = new int[26];
for (int i = 0; i < m; i++) {
arr[p.charAt(i) - 'a']++;
}
int a = 0;//记录个数
int b = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] != 0) a++;
}
for (int l = 0, r = 0; r < n; r++) {
if (--arr[s.charAt(r) - 'a'] == 0) b++;//计数增加
if (r - l + 1 > m && ++arr[s.charAt(l++) - 'a'] == 1) b--;//计数复原
if (a == b) list.add(l);
}
return list;
}
}