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

题目

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

这道题沿用上一题的思路,我会这么做

cpp 复制代码
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        unordered_map<string, vector<int>> mp;
        string p_p = p;
        sort(p_p.begin(), p_p.end());
        int i = 0, j = p.size();
        while (i + j <= s.size()) {
            string str = s.substr(i, j);
            sort(str.begin(), str.end());
            mp[str].emplace_back(i);
            i++;
        }
        return mp[p_p];
    }
};

代码是简洁了,思路也清晰,就是这个循环加上sort、substr这个时间开销太大了,导致最后运行超时

那么改如何优化呢

cpp 复制代码
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> ans;
        int n = s.size(), k = p.size();
        if(k > n) return ans; // p比s长,直接返回空

        vector<int> cntP(26,0);
        vector<int> cntS(26,0);

        // 统计p的字符频次
        for(char ch : p){
            cntP[ch - 'a']++;
        }

        // 先初始化第一个窗口 [0 , k‑1]
        for(int i = 0; i < k; i++){
            cntS[s[i] - 'a']++;
        }

        // 计算diff:频次不相等的字母总个数
        int diff = 0;
        for(int i = 0; i < 26; i++){
            if(cntS[i] != cntP[i]) diff++;
        }

        if(diff == 0){
            ans.emplace_back(0);
        }

        // 滑动窗口,窗口起点从1开始
        for(int l = 1; l <= n - k; l++){
            // 1.要移出窗口的字符:s[l‑1]
            char out = s[l - 1];
            int idxOut = out - 'a';
            // 移出之前,如果两边不等,移出之后有可能相等,diff变化
            if(cntS[idxOut] == cntP[idxOut]) diff++; //相等的话就要加,说明改字符后不匹配的
            cntS[idxOut]--; //正常移动窗口提走字母
            if(cntS[idxOut] == cntP[idxOut]) diff--; //如果相减后匹配,则说明diff可以减一

            // 2.新进入窗口的字符:s[l + k -1]
            char in = s[l + k -1];
            int idxIn = in - 'a';
            if(cntS[idxIn] == cntP[idxIn]) diff++;
            cntS[idxIn]++;
            if(cntS[idxIn] == cntP[idxIn]) diff--;

            // diff为0,窗口匹配
            if(diff == 0){
                ans.emplace_back(l);
            }
        }
        return ans;
    }
};

移动窗口不熟悉,多想想

相关推荐
学电子她就能回来吗23 分钟前
LeetCode Hot 100|普通数组专题学习笔记(零基础版)
笔记·算法·leetcode
用户老李24 分钟前
反向传播计算梯度举例
算法
niyongsheng26 分钟前
多智能体连续时间内路径规划:AA-SIPP(m) 的 Rust 实现与算法
算法·rust·机器人
302wanger1 小时前
DeepSeek-V4.1-Flash-1017 免费用到1024,速来
算法
lisw052 小时前
微分与积分的本质区别解析
算法·数学建模·极限编程
xys_6782 小时前
深挖数据结构:树和二叉树(上)
数据结构·算法
BeiGuTing_code2 小时前
Java动态数组(一)
java·数据结构·windows
Interview Aid1123 小时前
Google SWE Intern VO 面经:两轮 Coding,Follow-up 考察 BFS 状态
算法
琳达爱分享3 小时前
从单机令牌桶到集群限流:一次配额超发的复盘
后端·算法
range3 小时前
带TTL的LRU缓存的实现-字节手撕-26/10/19
算法