LeetCode438 找到字符串中所有字母异位词

LeetCode438 找到字符串中所有字母异位词

  • 题目
  • 解题:滑动窗口 + 双指针

题目

LeetCode438 找到字符串中所有字母异位词_第1张图片

解题:滑动窗口 + 双指针

LeetCode76 最小覆盖子串 同样使用滑动窗口 + 双指针来解题。下面一版的代码也与其类似,两道问题的不同之处在于:76题返回的最短字符串里面包含 p 的异位词,长度可以比 p 长,可以包含 p 以外的字母等,只要从中选取的一组字符可以构成 p 的异位词就成。

438题找的是异位词,长度和每个字符的个数都要相同。

sFreq 只记录在 p 中出现的字符的频数。 从提交结果来看,用数组来实现 sFreq 效率更高。

用 sFreq.clear(); / sFreq.fill(0); 的写法不能用一个哈希表来代替 sFreq 和 pFreq,因为在清除时,会把 p 中字符频数的信息一起抹去。

// javascript
var findAnagrams = function(s, p) {
   
    const sFreq = new Map(), pFreq = new Map();
    const sLen = s.length, pLen = p.length;
    // pFreq 记录 p 所有字符频数
    for (const pEle of p) {
   
        pFreq.set(pEle, (pFreq.get(pEle) || 0) + 1);
    }
    const res = [];
    // 左右指针 left 和 right, matchSuccess 记录有多少个字符频数 >= pFreq
    let left = 0, right = 0, matchSuccess = 0;
    while (right < sLen) {
   
        if (pFreq.has(s[right]) === true) {
   
            sFreq.set(s[right], (sFreq.get(s[right]) || 0) + 1);
            if (sFreq.get(s[right]) === pFreq.get(s[right])) {
   
                matchSuccess += 1;
            }          
        } else {
   
        	// [left, right]里如果包含不在 p 中的字符,那必定不是 p 的异位词
        	// left 指向 s[right] 的后一位,并且将 matchSuccess 和 sFreq 记录清除
        	// 新一轮的扫描时 left = right,并且该值还未处理,相当于窗口里没有字符
            left = right + 1;
            matchSuccess = 0;
            sFreq.clear();
        }
        // s 涵盖 p 所有字符且 left <= right 时:开始收缩窗口
        

你可能感兴趣的:(刷题笔记,哈希表,字符串,滑动窗口,双指针)