150.Find All Anagrams in a String(寻找字符串中所有变位词)

题目:

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。

 

posted @ 2018-09-09 15:19  chan_ai_chao  阅读(140)  评论(0编辑  收藏  举报