给定两个字符串 s
和 p
,找到 s
中所有 p
的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
示例 2:
输入: 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
仅包含小写字母1.解题思路
把两个字符串映射在两个int数组中。大小为26,刚好为26个小写字母的长度。
两个数组假设为sCount和pCount。长度以小的那种字符串为主,然后进行逐一比较
sCount假设为abcabc
只取三位为从a开始为1110000…
只取三位从b开始为0111000…
pCount假设为abc
abc为1110000…
设置两个指针分别对应left和right
for 循环中的 i 为遍历sCount的长度
先写一下
class Solution { public List<Integer> findAnagrams(String s, String p) { List<Integer> list = new ArrayList<>(); int[]sCount = new int[26]; int[]pCount = new int[26]; for(int i = 0 ;i<p.length();i++){//遍历小字符串 int num1 = s.charAt(i)-'a';//利用char字符的ASCII码值判断在数组哪个位置加一,A为65,小a为97,z为122 int num2 = p.charAt(i)-'a';//a-a=0,z-a=25,此处为索引值,其实已经是第26了 sCount[num1]++; //分别加一 sCount[num2]++; } for(int i = 0 ;i<s.length();i++){ //这次遍历大字符串s if(Arrays.equals(sCount, pCount)){ list.add(i) //如果一样就加入当前索引 } } return list ; //先返回 } }
完善逻辑,大字符串是变化的,那么他的sCout数组也是变化的,要加入双指针,进行滑动窗口的框选
public List<Integer> findAnagrams(String s, String p) { List<Integer> list = new ArrayList<>(); if (s == null || p == null || s.length() < p.length()) // 排除意外条件 return listt; int[]sCount = new int[26]; //构建26位字母的数组表,由索引来分辨是哪个字母,然后就加一 int[]pCount = new int[26]; for(int i = 0 ;i<p.length();i++){ int num1 = s.charAt(i)-'a';//利用char字符的ASCII码值判断在数组哪个位置加一,A为65,小a为97,z为122 int num2 = p.charAt(i)-'a';//a-a=0,z-a=25,此处为索引值,其实已经是第26了 sCount[num1]++; //分别加一 pCount[num2]++; } if(Arrays.equals(sCount, pCount)){//先判断一下索引0是否一样 list.add(0); } int left = 0; //构建浮动窗口 int right =left+ p.length()-1; while(true){ //这次遍历大字符串s sCount[s.charAt(left) - 'a']--; //删除浮动窗口中第一个元素的值,在大窗口中 left++; right++; if(right >= s.length()) //大数组剩余未判断元素个数 小于小数组的元素个数,直接返回 break; sCount[s.charAt(right)-'a']++; //添加浮动窗口中最后一个元素的值,在大窗口中 if(Arrays.equals(sCount, pCount)){ list.add(left) ; //如果一样就加入当前索引 } } return list ; //先返回 }