LongDz 的数字文墨提案

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

3 min

题目

解法:滑动窗口

思路

核心思想是使用滑动窗口配合字符计数数组。通过维护与p等长的窗口,动态调整左右指针确保窗口内字符频率与p一致。

正确性在于:当窗口长度等于p长度且字符计数完全匹配时即为异位词。移动右指针扩展窗口时增加字符计数,若某字符超量则移动左指针收缩窗口直至恢复有效状态,该过程保证不会遗漏任何有效窗口。

  • Step 1: 初始化p的字符计数数组num
  • Step 2: 用now数组记录当前窗口字符计数,left指针起始为0
  • Step 3: 遍历s扩展右指针,更新now计数
  • Step 4: 若当前字符超量则收缩左指针直至恢复有效
  • Step 5: 窗口长度等于p时记录左指针位置

复杂度

  • 时间复杂度: O(n)O(n),n为s长度,每个字符最多被左右指针各访问一次
  • 空间复杂度: O(1)O(1),固定使用两个长度26的计数数组

代码

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> num(26, 0);
        for (auto c : p) {
            num[c - 'a']++;
        }

        vector<int> ans;
        vector<int> now(26, 0);
        int left = 0;

        for (int right = 0; right < s.size(); right++) {
            int r_idx = s[right] - 'a';
            now[r_idx]++;
            while (now[r_idx] > num[r_idx]) {
                int l_idx = s[left] - 'a';
                now[l_idx]--;
                left++;
            }
            if (right - left + 1 == p.size()) {
                ans.push_back(left);
            }
        }
        return ans;
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> num(26, 0);
        for (auto c : p) {
            num[c - 'a']++;
        }

        vector<int> ans;
        vector<int> now(26, 0);
        int left = 0;

        for (int right = 0; right < s.size(); right++) {
            int r_idx = s[right] - 'a';
            now[r_idx]++;
            while (now[r_idx] > num[r_idx]) {
                int l_idx = s[left] - 'a';
                now[l_idx]--;
                left++;
            }
            if (right - left + 1 == p.size()) {
                ans.push_back(left);
            }
        }
        return ans;
    }
};