题目:
Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.
给定一个字符串s和一个非空字符串p,找到s中p的变位词的所有起始索引。
Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
字符串仅由小写英文字母组成,字符串s和p的长度不会大于20,100。
The order of output does not matter.
输出顺序无关紧要。
Example 1:
Input: s: "cbaebabacd" p: "abc" Output: [0, 6] Explanation: The substring with start index = 0 is "cba", which is an anagram of "abc". The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:
Input: s: "abab" p: "ab" Output: [0, 1, 2] Explanation: The substring with start index = 0 is "ab", which is an anagram of "ab". The substring with start index = 1 is "ba", which is an anagram of "ab". The substring with start index = 2 is "ab", which is an anagram of "ab".
解答:
自己理解写的:
1 class Solution { 2 public List<Integer> findAnagrams(String s, String p) { 3 List<Integer> res=new LinkedList<>(); 4 if (s == null || s.length() == 0 || p == null || p.length() == 0) return res; 5 int left=0,right=0,count=p.length(); 6 int[] hash=new int[256]; 7 for(char c:p.toCharArray()) 8 hash[c]++; 9 while(right<s.length()){ 10 //1 11 if(hash[s.charAt(right)]>0) count--; 12 hash[s.charAt(right)]--; 13 right++; 14 //2 15 if(count==0) res.add(left); 16 //3 17 if(right-left==p.length()){ 18 if(hash[s.charAt(left)]>=0) count++; 19 hash[s.charAt(left)]++; 20 left++; 21 } 22 } 23 return res; 24 } 25 }
精简写法:
1 class Solution { 2 public List<Integer> findAnagrams(String s, String p) { 3 List<Integer> res=new LinkedList<>(); 4 if (s == null || s.length() == 0 || p == null || p.length() == 0) return res; 5 int left=0,right=0,count=p.length(); 6 int[] hash=new int[256]; 7 for(char c:p.toCharArray()) 8 hash[c]++; 9 while(right<s.length()){ 10 if(hash[s.charAt(right++)]-->0) count--; 11 if(count==0) res.add(left); 12 if(right-left==p.length() && hash[s.charAt(left++)]++>=0) count++; 13 } 14 return res; 15 } 16 }
详解:
滑动窗口--双指针+hashmap(这里可以用大小为256的数组代替,位置代表该字符ASCII码对应的数字,数组的内容是出现的次数)。
left,right分别表示滑动窗口的左右边界,count表示p中需要匹配的字符个数(也是差异度)。
如果右边界所指的字符已经在hash表中,说明该字符在p中,count减1,hash表中该字符减1,右边界加1。
如果count==0,说明p中的字符都在s中,将left加入结果中。
如果right-left=p的长度,则应将最左边的字符去掉,如果该字符在hashmap中的个数大于等于0,说明该字符在p中,否则原来在hash表中为0,减1后应为-1,如果去掉了属于p的字符,count(差异度)加1。