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".
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--;
                System.out.print(counter + " ");
                System.out.println(c + " " + map.get(c));
            }
            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);
                }
                System.out.println("begin " + begin);
                begin++;
            }
            
        }
        return result;
    }
}

https://leetcode.com/problems/find-all-anagrams-in-a-string/discuss/92007/Sliding-Window-algorithm-template-to-solve-all-the-Leetcode-substring-search-problem.'

这种方法固然好,但有点繁琐啊

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        int[] hash = new int[26];
        int sle = s.length(), ple = p.length();
        for(char c : p.toCharArray()) hash[c - 'a']++;
        char[] sarr = s.toCharArray();
        List<Integer> res = new ArrayList();
        
        int count = 0, l = 0;
        for(int r = 0; r < sle; r++) {
            hash[sarr[r] - 'a']--;
            if(hash[sarr[r] - 'a'] >= 0) count++;
            
            if(r - l + 1 > ple) {
                hash[sarr[l] - 'a']++;
                if(hash[sarr[l] - 'a'] > 0) count--;
                l++;
            }
            if(count == ple) res.add(l);
        }
        return res;
    }
}

首先它是一个固定长度的window,然后套用模板,先给每个p string里的char hash一下,然后用count来表示当前有效长度,当有效长度==p。length(),说明找到了一个有效substring,即从l到r。

从左向右遍历,先hash--,如果hash仍然≥0,说明当前是一个有效的char,count++。

然后是判断window缩小条件,r-l + 1》ple,说明window过长,需要减小一位。

现在要把左边l的hash还回去,还要判断还回去的是不是有效的char,如果是的话,count--。记得l++来保证window size正常。

最后就是判断count == ple时,就是一个正确答案。

https://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=544207&page=1

参考这位大佬的模板,更加简洁

模板分为

public int slidingWindowTemplate(String[] a, ...) {
    // 输入参数有效性判断
    if (...) {
        ...
    }
     
    // 申请一个散列,用于记录窗口中具体元素的个数情况
    // 这里用数组的形式呈现,也可以考虑其他数据结构
    int[] hash = new int[...];
     
    // 预处理(可省), 一般情况是改变 hash
    ...
     
    // l 表示左指针
    // count 记录当前的条件,具体根据题目要求来定义
    // result 用来存放结果
    int l = 0, count = ..., result = ...;
    for (int r = 0; r < A.length; ++r) {
        // 更新新元素在散列中的数量
        hash[A[r]]--;
         
        // 根据窗口的变更结果来改变条件值
        if (hash[A[r]] == ...) {
            count++;
        }
         
        // 如果当前条件不满足,移动左指针直至条件满足为止
        while (count > K || ...) {
            ...
            if (...) {
                count--;
            }
            hash[A[l]]++;
            l++;
        }
         
        // 更新结果
        results = ...
    }
     
    return results;
}

很好很强大

posted @ 2020-05-18 09:48  Schwifty  阅读(163)  评论(0编辑  收藏  举报