LeeCode_76.最小覆盖子串(滑动窗口)

本文介绍了如何使用滑动窗口算法解决LeetCode上的《最小覆盖子串》问题。通过设置左右指针并维护一个需求字符计数器,逐步移动指针找到包含目标字符串所有字符的最小子串。在移动过程中更新字符计数,并适时移动左指针以缩短子串长度。算法详细步骤和代码实现使得问题解决过程清晰易懂。

 一、介绍

1.题目描述

题目链接:https://leetcode-cn.com/problems/minimum-window-substring/

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

2.测试样例

"ADOBECODEBANC"
"ABC"
# "BANC"

"a"
"a"
# "a"

"a"
"aa"
# ""

二、题解_滑动窗口🟡

官方视频演示参考:https://leetcode-cn.com/problems/minimum-window-substring/solution/shu-ju-jie-gou-he-suan-fa-hua-dong-chuan-p6ip/

原理:

1、起始时左右指针均为0,用 start 和 len 分别记录解的起始位置和长度【start=0,len=INT_MAX】

2、右指针向右移动,直到 左右指针之间的字符串包含 t 中全部字符【即可作为一个解】

3、若该解的长度 < len ,更新 start 和 len

4、移动左指针,直到 左右指针之间的字符串 不再 包含 t 中全部字符

5、循环234步骤,直到 r > 字符串 s 的长度

  • 用 count 记录需要的字符总个数,即需求个数
  • 用 map数组 记录所需的各个字符个数
  • 用 flag数组 记录该字符是否在 t 中
  • 每次左右指针移动,都对map 进行更新,map[i] < 0代表过剩,>0代表有需求
  • 借助字母的ASCⅡ码来记录,值最多差58
class Solution {
public:
    string minWindow(string s, string t) {
        if(s==t||t=="") return t;
        if(s.length()<t.length()) return "";
        // map记录t中各元素及个数,map[i]>0代表该字母有需求
        int map[58];
        // 标记t中是否有该元素
        int flag[58];
        for(int i=0;i<58;i++){
            map[i]=0;flag[i]=0;
        }
        for(int i=0;i<t.length();i++){
            map[t[i]-'A']++;
            flag[t[i]-'A']=1;
        }
        int n=s.length();
        // 双指针初始均为0,count记录t的字母个数
        int l=0,r=0,count=t.length();
        // 记录解的起始坐标和长度
        int start=0,len=INT_MAX;
        while(r<n){
            // 当有需求的字母出现时,count--
            if(map[s[r]-'A']>0) count--;
            // 更新map
            map[s[r]-'A']--;
            // 当字符串已经包含t的全部内容(即需求=0),移动左指针,直到不满足条件
            while(count==0){
                if(r-l+1<len){
                    start=l;
                    len=r-l+1;
                }
                // map[i]<0代表该字母过剩
                // 如果左指针当前指向的字母在t中,且不过剩,需求个数增加
                if(flag[s[l]-'A']==1&&map[s[l]-'A']>=0){
                    count++;
                }
                // 更新map
                map[s[l]-'A']++;
                l++;
            }
            // 移动右指针
            r++;
        }
        // 如果无解,返回空
        if(len>n)return "";
        return s.substr(start,len);
    }
};

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值