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:

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".

解釋下題目:

判斷一個字符串里anagram的個數。

1. 老老實實判斷

實際耗時:856ms

public List<Integer> findAnagrams(String s, String p) {
    List<Integer> res = new ArrayList<>();
    for (int i = 0; i <= s.length() - p.length(); i++) {
        String tmp = s.substring(i, i + p.length());
        if (isAnagram(tmp, p)) {
            res.add(i);
        }
    }
    return res;
}

public boolean isAnagram(String s, String t) {
    if (s.length() != t.length()) {
        //長度都不相同還怎么可能是
        return false;
    }
    int[] arr = new int[26];

    for (int i = 0; i < s.length(); i++) {
        arr[s.charAt(i) - 'a']++;
        arr[t.charAt(i) - 'a']--;
    }
    for (int i = 0; i < s.length(); i++) {
        if (arr[s.charAt(i) - 'a'] != 0) {
            return false;
        }
    }

    return true;
}

??思路不說了,簡單粗暴。

時間復雜度O(n*m) n為s的長度,m為p的長度。
空間復雜度O(1)

2. 滑動窗口

實際耗時:8ms

public List<Integer> findAnagrams2(String s, String p) {
    List<Integer> res = new ArrayList<>();
    if (s == null || s.length() == 0 || p == null || p.length() == 0) return res;
    int[] table = new int[256];
    for (char c : p.toCharArray()) {
        table[c]++;
    }
    int left = 0, right = 0, count = 0;
    while (right < s.length()) {
        if (table[s.charAt(right)] > 0) {
            count++;
        }
        table[s.charAt(right)]--;
        right++;

        if (count == p.length()) {
            res.add(left);
        }

        if (right - left == p.length()) {
            if (table[s.charAt(left)] >= 0) {
                count--;
            }
            table[s.charAt(left)]++;
            left++;
        }

    }
    return res;
}

??其實一說滑動窗口就差不多都明白了,省力在如果p很長的情況下,有一大部分其實是可以省略判斷的,有點像動態規劃,所以那么省。需要注意的是,滑動窗口往右邊移動的時候,如果劃入窗口的那個字母不存在于table中,還是需要減一的,也就是table中的元素可能是負的,這一點我當時沒想通,導致左邊滑入的時候count無法做判斷,想了半天。

時間復雜度O(n)
空間復雜度O(1)

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容