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

0 阅读2分钟

你好,我是本文作者南一。如果有发现错误或者可完善的地方,恳请斧正,万分感谢!!

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

先尝试暴力解...

将 p 字符串每一个字符用 map 保存,并记录个数;遍历 s 字符串一个个匹配,直到有符合的,即所有字符用完的字符串就 push 到结果集。

思路正确,但是超时了...

var findAnagrams = function (s, p) {
  const map = {};

  for (let i = 0; i < p.length; i++) {
    if (map[p[i]]) {
      map[p[i]]++;
    } else {
      map[p[i]] = 1;
    }
  }

  const result = [];

  for (let i = 0; i < s.length; i++) {
    let j = i,
      cloneMap = { ...map };
    while (j < s.length && cloneMap[s[j]]) {
      cloneMap[s[j]]--;
      j++;
    }
    if (j - i === p.length) {
      result.push(i);
    }
  }

  return result;
};

再试试双指针滑动窗口,顺利通过!!!

var findAnagrams = function (s, p) {
  // 第一步 收集 p 所有字符存在 map中
  const map = {};

  for (let i = 0; i < p.length; i++) {
    if (map[p[i]]) {
      map[p[i]]++;
    } else {
      map[p[i]] = 1;
    }
  }

  const result = [];

  // 第二步 双指针滑动窗口;核心思路:使 [i, j] 区间内就是要找的异位词
  let i = 0,
    j = i;
  while (i <= j && j <= s.length) {
    if (map[s[j]]) {
      map[s[j]]--;
      j++;
    } else {
      // 当 j 指针所指字符 不在 map 中时,存在两种情况  1. s[i] 不在p中; 2. s[i] 在p中 但是个数用完了

      // 1. 长度=== p的长度,那么 [i, j] 区间内就是要找的异位词
      if (j - i === p.length) {
        result.push(i);
      }

      // 2. j和i相等,此时没消耗过map中的字符,那么只能是 s[i] 不在p中。
      // 此时需要 i 和 j 都往前走一步,因为只要区间[i, j] 包含了当前 s[i] 那他就永远不可能是异位词
      if (j === i) {
        j++;
      } else {
        // 恢复 s[i] 在map中的字符个数。
        // 为什么是在 j !== i 的逻辑中恢复呢?因为不能把不在 p 中的 s[i] 给记录下来。
        map[s[i]]++;
      }
      i++;
    }
  }

  return result;
};