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;
    }
};

移动窗口不熟悉,多想想

相关推荐
weixin_307779134 分钟前
C++代码实现MATLAB中的pade函数功能
开发语言·c++·算法·matlab
smj2302_796826527 分钟前
解决leetcode第4064题至多一次取反能被k整除的最长子数组II
python·算法·leetcode
AIGC小尼11 分钟前
ACE-Step-1.5 本地 AI 音乐模型实战|text2music 歌词转人声,部署脚本、参数调优与排坑全记录
人工智能·算法·comfyui·ai漫剧
YOLO数据集集合18 分钟前
树木检测数据集 | 树木检测 树种分类 航拍林业 森林监测9131期
人工智能·算法·机器学习·分类·数据挖掘·林业·树种分类
青山木23 分钟前
Hot 100 --- 下一个排列
java·数据结构·算法·leetcode
垆边人似月.26 分钟前
字符串重排后最大字典序
算法·leetcode·职场和发展
码流子27 分钟前
AI稽核精灵-Agent落地
大数据·人工智能·物联网·算法·系统架构
微三云生态系统架构师-彭丹36 分钟前
排队免单资金池专户存管与返本算法:队列模型与熔断保护
算法·熔断机制·排队免单·消费增值·资金池·队列系统·返本算法
wzdark43 分钟前
矩阵快速幂算法在图路径计算中的应用4
线性代数·算法·矩阵
Dylan的码园1 小时前
A+B问题 进制处理【逻辑控制 运算符】
c++·算法