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

移动窗口不熟悉,多想想

相关推荐
GoAI6 小时前
DeepSeek Harness Memory (一)主流记忆插件总结
后端·算法·面试
Pniubi7 小时前
力扣54.螺旋矩阵
算法·leetcode·矩阵
choumou_M9 小时前
算法_1:由浅入深学习快速排序QuickSort
学习·算法·排序算法
Coder_Shenshen10 小时前
罗克韦尔ACD工程归档离线变量树解析
算法·c#
心仪久了会沦陷11 小时前
C语言数据结构入门——树与二叉树详解:概念、堆实现与链式遍历
c语言·数据结构·算法
小此方12 小时前
[算法实战论:动态规划]背包问题概念,01不满背包问题,01满背包问题,背包问题的滚动数组空间优化
算法·动态规划
悠仁さん13 小时前
【C++】哈希表
c++·算法·散列表
码少女13 小时前
数据结构——图的基础
数据结构
地平线开发者13 小时前
点云算法整理与常用计算模块:从数据到模型,再到工程与量化
算法·自动驾驶