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

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

  • 不重新扫描窗口

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

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

相关推荐
君义_noip1 天前
信息学奥赛一本通 1661:有趣的数列 | 洛谷 P3200 [HNOI2009] 有趣的数列
c++·算法·组合数学·信息学奥赛·csp-s
程序员:钧念1 天前
深度学习与强化学习的区别
人工智能·python·深度学习·算法·transformer·rag
英英_1 天前
MATLAB数值计算基础教程
数据结构·算法·matlab
一起养小猫1 天前
LeetCode100天Day14-轮转数组与买卖股票最佳时机
算法·leetcode·职场和发展
hele_two1 天前
快速幂算法
c++·python·算法
l1t1 天前
利用DeepSeek将python DLX求解数独程序格式化并改成3.x版本
开发语言·python·算法·数独
jllllyuz1 天前
基于子集模拟的系统与静态可靠性分析及Matlab优化算法实现
算法·matlab·概率论
程序员-King.1 天前
day143—递归—对称二叉树(LeetCode-101)
数据结构·算法·leetcode·二叉树·递归
BlockChain8881 天前
字符串最后一个单词的长度
算法·go
爱吃泡芙的小白白1 天前
深入解析:2024年AI大模型核心算法与应用全景
人工智能·算法·大模型算法