这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战
- 题目:给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。异位词: 指由相同字母重排列形成的字符串(包括相同的字符串)
- 实现代码
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res = new ArrayList<>();
int[] d1 = new int[26]; // 记录 s 串的状态
int[] d2 = new int[26]; // 记录 p 串的状态
char[] c1 = s.toCharArray(); // 算法书上说明这样写会比 s.CharAt(i) 快很多,但是
char[] c2 = p.toCharArray(); // 在题目中好像不明显,应该是数据量不够的大的原因。
int n1 = c1.length;
int n2 = c2.length;
if (n1 < n2) return res;
for (int i = 0; i < n2; i++) { // 记录它们的初始状态
d1[c1[i] - 'a']++;
d2[c2[i] - 'a']++;
}
if (Arrays.equals(d1,d2)) { // 用 Arrays 内置的数组比较方法,可能会比我们写的快吧!
res.add(0);
}
for (int i = 0; i < n1 - n2; i++) {
d1[c1[i] - 'a']--; // 维护滑动窗口的头部(减少)
d1[c1[i + n2] - 'a']++; // 维护滑动窗口的尾部(增加)
if (Arrays.equals(d1,d2)) {
res.add(i + 1);
}
}
return res;
}
- 根据题目的表述,我们首先很快就会想到用普通的滑动窗口可能就可以了,其实并不然。
- 因为题目要求我们的不是给出字符串的 子串 ,如果单用滑动窗口的话就行不通了;于是我们可能会想到用哈希表来维护匹配的状态,虽然理论上是可行的,这时候就想一下,每一次都要对哈希表中的字母个数的状态进行更新,此时为了更加方便,我们还可以常量记录 p 串中字母的状态。不过想到这里的时候,会不会有更好的数据结构来维护呢?哈哈,那是肯定的!
- 用数组来维护滑动窗口内字母个数的状态,开辟一个长度为 26 的数组就可以维护所有出现的状态了。见代码注解。