[LeetCode] 438. 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.

Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 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".

给一个字符串s和一个非空字符串p,找出s中所有的p的变位词的index。

解法:滑动窗口法,双指针。

Java:

class Solution {
       public List<Integer> findAnagrams(String s, String p) {
           int left = 0;
           int right = 0;
           int matchSize = p.length();
           int[] map = new int[256];
           List<Integer> res = new ArrayList<>();
           // count the char number in p 计算p中各个字符的数量
           for (char c:p.toCharArray()){
               map[c] ++;
           }
           
           
           // build window 开始进行sliding window
           while (right < s.length()){
               // this char exists in p  
               // 如果当前的char是存在于p中,则目标大小matchsize就得减少
               // 判断标准就是他的值不是为-1
               if (map[s.charAt(right)] > 0)
                   matchSize --;
                map[s.charAt(right)] --;
               
               if (right - left == p.length()-1){
                   // check matchSize equals to 0
                   // 如果此时目标大小也是0,说明这就是需要的一个子串
                   if (matchSize == 0)
                       // add the left index
                       res.add(left);
                   
                   // move left pointer to start new search
                   // 如果当这个字符原来是p中的话,现在移动指针需要还原以前原有的matchSize,开始新的搜索
                   if (map[s.charAt(left)] >= 0)
                       matchSize ++;
                   // 还原以前每个元素减去的1
                   map[s.charAt(left)]++;
                   left++;
               }
              right++;
           }
           
           return res;
    }
}

Java:

public class Solution {
    public List<Integer> findAnagrams(String s, String t) {
        List<Integer> result = new LinkedList<>();
        if(t.length()> s.length()) return result;
        Map<Character, Integer> map = new HashMap<>();
        for(char c : t.toCharArray()){
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        int counter = map.size();
        
        int begin = 0, end = 0;
        int head = 0;
        int len = Integer.MAX_VALUE;
        
        
        while(end < s.length()){
            char c = s.charAt(end);
            if( map.containsKey(c) ){
                map.put(c, map.get(c)-1);
                if(map.get(c) == 0) counter--;
            }
            end++;
            
            while(counter == 0){
                char tempc = s.charAt(begin);
                if(map.containsKey(tempc)){
                    map.put(tempc, map.get(tempc) + 1);
                    if(map.get(tempc) > 0){
                        counter++;
                    }
                }
                if(end-begin == t.length()){
                    result.add(begin);
                }
                begin++;
            }
            
        }
        return result;
    }
} 

Python:

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        result = []

        cnts = [0] * 26
        for c in p:
            cnts[ord(c) - ord('a')] += 1

        left, right = 0, 0
        while right < len(s):
            cnts[ord(s[right]) - ord('a')] -= 1
            while left <= right and cnts[ord(s[right]) - ord('a')] < 0:
                cnts[ord(s[left]) - ord('a')] += 1
                left += 1
            if right - left + 1 == len(p):
                result.append(left)
            right += 1

        return result

Python: wo

class Solution(object):
    def findAnagrams(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: List[int]
        """
        n = len(p)
        counts = [0] * 26
        for i in p:
            counts[ord(i) - ord('a')] += 1
            
        res = []
        for i in xrange(len(s)):
            counts[ord(s[i]) -  ord('a')] -= 1
            if i >= n:
                counts[ord(s[i - n]) - ord('a')] += 1
            if self.checkAllZero(counts):
                res.append(i - n + 1)
            
        return res            
            
    def checkAllZero(self, counts):           
        for i in counts:
            if i != 0:
                return False
            
        return True   

C++:

// Time:  O(n)
// Space: O(1)
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> result;
        if (p.empty() || s.empty()) {
            return result;
        }

        vector<int> cnts(26);
        for (const auto& c : p) {
            ++cnts[c - 'a'];
        }
        
        for (int left = 0, right = 0; right < s.length(); ++right) {
            --cnts[s[right] - 'a'];
            while (left <= right && cnts[s[right] - 'a'] < 0) {
                ++cnts[s[left++] - 'a'];
            }
            if (right - left + 1 == p.length()) {
                result.emplace_back(left);
            }
        }
        return result;
    }
};

C++:  

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        if (s.empty()) return {};
        vector<int> res, m(256, 0);
        int left = 0, right = 0, cnt = p.size(), n = s.size();
        for (char c : p) ++m[c];
        while (right < n) {
            if (m[s[right++]]-- >= 1) --cnt;
            if (cnt == 0) res.push_back(left);
            if (right - left == p.size() && m[s[left++]]++ >= 0) ++cnt;
        }
        return res;
    }
};

  

类似题目:

[LeetCode] 242. Valid Anagram 验证变位词

[LeetCode] 567. Permutation in String 字符串中的全排列

 

 

All LeetCode Questions List 题目汇总

 

 

posted @ 2018-10-10 08:36  轻风舞动  阅读(531)  评论(0编辑  收藏  举报