一题吃透滑动窗口:巧解字母异位词

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

题目分析

给定两个字符串 sp,找出 s 中所有是 p 异位词的子串起始索引。
异位词是指字符串字符组成相同但顺序不同的字符串。


思路

  • 异位词的定义是字符频次相同,所以我们需要判断子串字符频次是否和 p 相同。

  • 用一个大小为 26 的数组统计 p 中字符频次,另一个数组动态维护滑动窗口中字符频次。

  • 使用滑动窗口,窗口大小固定为 p 的长度。

  • 窗口每右移一次:

    • 新字符频次加 1
    • 窗口超过长度时,移除左边字符频次
  • 每次窗口大小等于 p 长度时,比较两个频次数组,相等则说明找到一个异位词。


代码

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> sCnt(26, 0), pCnt(26, 0);
        vector<int> ans;
        int n = s.size(), m = p.size();
        if (n < m) return ans;

        // 统计p中字符频次
        for (char c : p) {
            pCnt[c - 'a']++;
        }

        int l = 0;
        for (int r = 0; r < n; ++r) {
            sCnt[s[r] - 'a']++;

            // 窗口超过p长度时,左边字符频次减一,左指针右移
            if (r - l + 1 > m) {
                sCnt[s[l] - 'a']--;
                l++;
            }

            // 窗口大小等于p长度时比较频次数组
            if (r - l + 1 == m && sCnt == pCnt) {
                ans.push_back(l);
            }
        }
        return ans;
    }
};

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),遍历 s 一次,频次数组比较为 O ( 26 ) O(26) O(26) 视为常数。
  • 空间复杂度: O ( 1 ) O(1) O(1),使用固定大小频次数组。

定长滑动窗口模板

void fixedLengthSlidingWindow(const vector<int>& arr, int k) {
    int n = arr.size();
    if (k > n) return;

    // 这里可以存一些窗口内的信息,比如窗口和、频率、最大值等
    int window_sum = 0;

    // 先处理第一个窗口
    for (int i = 0; i < k; ++i) {
        window_sum += arr[i];
    }
    cout << "Window [0, " << k - 1 << "] sum = " << window_sum << "\n";

    // 滑动窗口开始移动
    for (int i = k; i < n; ++i) {
        window_sum -= arr[i - k];  // 去掉左边的元素
        window_sum += arr[i];      // 加入右边的元素
        cout << "Window [" << i - k + 1 << ", " << i << "] sum = " << window_sum << "\n";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值