最小覆盖字串(滑动窗口)

该题使用滑动窗口的增量统计机制,

  • 不重新扫描窗口

  • 每次右边加一个字符、左边减一个字符,就更新一次计数

  • 判断窗口是否满足条件用 O(1)

一开始我使用虽然也是滑动窗口,但是类似于暴力求解,时间复杂度为O(N^2):因为每次左指针每滑动一次时,检查是否满足覆盖条件仍然是O(N),所以整体下来就是O(N^2)。

cpp 复制代码
class Solution {
public:
    
    bool IsCover(string& s, int left, int right,unordered_map<char,int> charnum){
        for(int i =left;i<=right;i++){
            auto it=charnum.find(s[i]);
            if(it!=charnum.end()){
                if(charnum[s[i]]!=0) charnum[s[i]]--;
                if(charnum[s[i]]==0) charnum.erase(it);
            }
        }
        return charnum.empty();
    }

    string minWindow(string s, string t) {
        unordered_map<char,int> charnum;
        for(auto e: t) charnum[e]++;
        int left=0; int right=0; int flag=0; int min_left=0; int min_right=0; int min=100000; int cur;
        while(left<=right && right<s.size()){
            if(IsCover(s,left,right,charnum)){
                flag=1; cur=right-left+1; 
                if(cur<min){min_left=left; min_right=right; min=cur;}
                left++;
            }
            else right++;
        }
        
        if(flag==0) return "";
        else{
            string s1(s.begin()+min_left,s.begin()+min_right+1);
            return s1;
        }
    }
};

要使整体时间复杂度达到 O(N) ,必须采用滑动窗口的"增量统计"方式。核心思想是维护一个 count,表示当前窗口中还缺多少个字符才能完全覆盖字符串 t

右指针扩张窗口时

  • s[r]t 中需要的字符(即哈希表 need[s[r]] > 0)时:

    • 说明我们弥补了一个缺失字符 → count--
  • 不论 need[s[r]] 是否大于 0,我们都执行 need[s[r]]--

    这是为了在窗口内部维持正确的剩余需求。

count == 0

说明当前窗口已经包含 t 需要的全部字符,可以开始尝试收缩左指针。

左指针收缩窗口时

  • 在收缩前,先将 need[s[l]]++

  • 如果 need[s[l]] 增加后 大于 0 ,表示窗口因移除 s[l] 而缺少了该字符

    • count++(窗口不再满足覆盖条件)

随后继续右移右指针,继续扩大窗口。

核心:need 是一个"差值计数器"

把 need 看成:

窗口中"缺少多少"这个字符(正数 = 缺,负数 = 多)

因此,随着窗口移动:

右指针进来一个字符 c

need[c]--

  • 如果 need[c] > 0,说明这个字符正是我们需要的

    → count--,表示距离满足目标更近了

  • 如果 need[c] <= 0,说明窗口中多出来了

    → 不影响 count


左指针移除一个字符 lc

need[lc]++

  • 如果 need[lc] > 0,说明刚移走的是一个必须字符

    → 再次缺失了 → count++

  • 如果 need[lc] <= 0,说明移走的是冗余字符

    → 不影响覆盖性

通过这种右 pointer 扩张、左 pointer 收缩的方式,我们可以保证每个字符最多被访问两次,因此整体时间复杂度为 O(N)

相关推荐
小O的算法实验室18 小时前
2026年ASOC,基于深度强化学习的无人机三维复杂环境分层自适应导航规划方法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
‎ദ്ദിᵔ.˛.ᵔ₎19 小时前
LIST 的相关知识
数据结构·list
M--Y19 小时前
Redis常用数据类型
数据结构·数据库·redis
郭涤生20 小时前
STL vector 扩容机制与自定义内存分配器设计分析
c++·算法
༾冬瓜大侠༿20 小时前
vector
c语言·开发语言·数据结构·c++·算法
Ricky111zzz20 小时前
leetcode学python记录1
python·算法·leetcode·职场和发展
汀、人工智能20 小时前
[特殊字符] 第58课:两个正序数组的中位数
数据结构·算法·数据库架构··数据流·两个正序数组的中位数
liu****20 小时前
第16届省赛蓝桥杯大赛C/C++大学B组(京津冀)
开发语言·数据结构·c++·算法·蓝桥杯
汀、人工智能20 小时前
[特殊字符] 第79课:分割等和子集
数据结构·算法·数据库架构·位运算·哈希表·分割等和子集
汀、人工智能20 小时前
[特殊字符] 第74课:完全平方数
数据结构·算法·数据库架构·图论·bfs·完全平方数