438. 找到字串中所有字母異位詞(暴力,雙指標)2

星河依然滾燙發表於2020-12-15

給定一個字串 s 和一個非空字串 p,找到 s 中所有是 p 的字母異位詞的子串,返回這些子串的起始索引。

字串只包含小寫英文字母,並且字串 s 和 p 的長度都不超過 20100。

說明:

字母異位詞指字母相同,但排列不同的字串。
不考慮答案輸出的順序。
示例 1:

輸入:
s: "cbaebabacd" p: "abc"

輸出:
[0, 6]

解釋:
起始索引等於 0 的子串是 "cba", 它是 "abc" 的字母異位詞。
起始索引等於 6 的子串是 "bac", 它是 "abc" 的字母異位詞。
 示例 2:

輸入:
s: "abab" p: "ab"

輸出:
[0, 1, 2]

解釋:
起始索引等於 0 的子串是 "ab", 它是 "ab" 的字母異位詞。
起始索引等於 1 的子串是 "ba", 它是 "ab" 的字母異位詞。
起始索引等於 2 的子串是 "ab", 它是 "ab" 的字母異位詞。

解法一:滑動視窗

class Solution {
    public List<Integer> findAnagrams(String s, String p) {

       // 先對目標串p每個字元進行字元計數,統計出每個字元的出現次數
       int pLength = p.length();
       int sLength = s.length();

       int[] counts = new int[26];
       for(int i = 0; i < pLength; i++){
            counts[p.charAt(i) - 'a']++;
       }

       ArrayList<Integer> res = new ArrayList<>();  // 儲存結果的結果集

        int[] tempCounts = new int[26]; // 記錄視窗內每種字元的出現次數
        int left = 0, right = 0;
        while(right < sLength){
            int curR = s.charAt(right) - 'a';
            tempCounts[curR]++;        // curR字元的出現次數加一
            right++;    // 新增一個字元後,視窗右指標右移一位
            while(tempCounts[curR] > counts[curR]){ // 不斷縮小視窗大小,直到把超標字元移出去一個,使得不超標
                tempCounts[s.charAt(left) - 'a']--;
                left++;     // 移走一個字元後視窗左指標右移一位
            }
            if(right - left == pLength){
                res.add(left);
            }
        }
        return res;
    }
}

相關文章