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

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

  • 不重新扫描窗口

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

  • 判断窗口是否满足条件用 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]--

  • 如果 needc > 0,说明这个字符正是我们需要的

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

  • 如果 needc <= 0,说明窗口中多出来了

    → 不影响 count


左指针移除一个字符 lc

need[lc]++

  • 如果 needlc > 0,说明刚移走的是一个必须字符

    → 再次缺失了 → count++

  • 如果 needlc <= 0,说明移走的是冗余字符

    → 不影响覆盖性

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

相关推荐
罗西的思考1 天前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
CSharp精选营1 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
美团技术团队1 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
_清歌3 天前
DSpark 深度解读:DeepSeek-V4 如何用「半自回归」把推理速度提升 85%
算法
统计实现局3 天前
SVD 的三步走:双对角化、Givens 收敛、排序
算法
躬行见万象3 天前
《VLA 系列》UniLab 强化训练 | G1 机器人 |复现
算法