题目:
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例:
输入: s = "cbaebabacd", p = "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。 起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
思路:
思路很简单,肯定是滑动窗口,可以用数组或者双指针实现。
用数组实现,我们先把短的遍历。把各个字母出现次数添加到数组里。然后遍历长的字符串,遍历相同长度之后把字母出现次数加到另一个数组再比较两数组。相同就记录起始位置。
后面长的字符串数组就滑起来,加一减一就可以。
见代码及注释
复杂度:
时间复杂度:遍历O(n)
空间复杂度:额外空间是常数级别O(1)
代码:
public List<Integer> findAnagrams(String s, String p) {
//思路很简单肯定是滑动窗口
int m = s.length();
int n = p.length();
//res来存档结果
List<Integer> res = new ArrayList<>();
//特殊情况
if(m<n) return res;
//来两个数组来记录s,p各个字母出现的次数
int sCount[]=new int[26];
int pCount[]=new int[26];
for(int i=0;i<n;++i){
//遍历p和s的p位,相应位置的数量增加
pCount[p.charAt(i) -'a']++;
sCount[s.charAt(i) -'a']++;
}
//如果恰好满足,就把0添入
if(Arrays.equals(pCount,sCount)) res.add(0);
//sCount开始往后滑动
for(int i=n;i<m;++i){
//新的进来旧的出去
sCount[s.charAt(i) -'a']++;
sCount[s.charAt(i-n) -'a']--;
//每滑一下都要做一次判断
if(Arrays.equals(pCount,sCount)) res.add(i-n+1);
}
return res;
}