Bootstrap

一起学习LeetCode热题100道(9/100)

9.找到字符串中所有字母异位词(学习)

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

示例 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” 的异位词。

提示:
1 <= s.length, p.length <= 3 * 104
s 和 p 仅包含小写字母

var findAnagrams = function(s, p) {
    const result = [];  
    const pLength = p.length;  
    const sLength = s.length;  
  
    // 如果p的长度大于s,则不可能存在p的异位词  
    if (pLength > sLength) {  
        return result;  
    }  
  
    // 初始化两个哈希表,分别用于存储p和当前窗口的字符频率  
    const pFreq = {};  
    const windowFreq = {};  
  
    // 填充pFreq哈希表  
    for (let char of p) {  
        if (!pFreq[char]) {  
            pFreq[char] = 0;  
        }  
        pFreq[char]++;  
    }  
  
    // 初始化窗口  
    let left = 0;  
    let matched = 0; // 记录当前窗口内匹配p的字符数量  
  
    // 滑动窗口  
    for (let right = 0; right < sLength; right++) {  
        const char = s[right];  
  
        // 如果当前字符在p中,则增加其频率  
        if (pFreq[char]) {  
            if (!windowFreq[char]) {  
                windowFreq[char] = 0;  
            }  
            windowFreq[char]++;  
  
            // 如果当前字符的频率与p中一致,则增加匹配数  
            if (windowFreq[char] === pFreq[char]) {  
                matched++;  
            }  
        }  
  
        // 当窗口大小等于p的长度时,检查是否所有字符都匹配  
        if (right - left + 1 === pLength) {  
            // 如果匹配数等于p中字符的种类数,则找到了一个异位词  
            if (matched === Object.keys(pFreq).length) {  
                result.push(left);  
            }  
  
            // 移动左指针,并更新窗口频率  
            const leftChar = s[left];  
            if (pFreq[leftChar]) {  
                if (windowFreq[leftChar] === pFreq[leftChar]) {  
                    matched--;  
                }  
                windowFreq[leftChar]--;  
  
                // 如果窗口频率中该字符为0,则删除该键  
                if (windowFreq[leftChar] === 0) {  
                    delete windowFreq[leftChar];  
                }  
            }  
  
            left++;  
        }  
    }  
  
    return result;  
};
;