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

文章介绍了一种利用滑动窗口和哈希映射解决在给定字符串s中找到最短连续子串,该子串包含另一个字符串t的所有字符的问题。通过维护一个哈希表记录t中字符的出现次数,并逐步移动窗口边界,直到找到满足条件的最小子串。
摘要由CSDN通过智能技术生成

最小覆盖子串_牛客题霸_牛客网【牛客题霸】收集各企业高频校招笔面试题目,配有官方题解,在线进行百度阿里腾讯网易等互联网名企笔试面试模拟考试练习,和牛人一起讨论经典试题,全面提升你的技术能力https://www.nowcoder.com/practice/c466d480d20c4c7c9d322d12ca7955ac

 描述

给出两个字符串 s 和 t,要求在 s 中找出最短的包含 t 中所有字符的连续子串。

例如:

S="XDOYEZODEYXNZ"S="XDOYEZODEYXNZ"
T="XYZ"T="XYZ"
找出的最短子串为"YXNZ""YXNZ".

注意:
如果 s 中没有包含 t 中所有字符的子串,返回空字符串 “”;
满足条件的子串可能有很多,但是题目保证满足条件的最短的子串唯一。

示例1

输入:"XDOYEZODEYXNZ","XYZ"返回值:"YXNZ"

示例2

输入:"abcAbA","AA"返回值:"AbA"

 思路:使用滑动窗口,进行划分,使用一个哈希map来存储T中每个字符的出现次数关系,先对T中每个元素进行遍历,出现一次mp++;到时候利用这个map容器来进行元素是否全都出现过了的判断

初始状态,left和right都在0号位置,对0号位置进行判断,如果为T中的字符,那么mp--

flag函数()如果当前map中所有的元素都小于等于0了,说明当前窗口中T的字符都有了

接着进入循环,

如果当前窗口中元素不能满足flag()判断函数,那么right++,并且对当前right位置元素进行判断,如果right位置元素为T中元素,那么就对对应map进行--表示该字符存在次数多了一次了

如果可以满足flag了那么就说明当前元素中满足都出现T中所有字符,对当前left位置和长度进行保存,使用俩个变量保存这个left位置与长度,并不断维护一个长度最小的区间,接着left就可以进行后续移动。


#include <linux/limits.h>
class Solution {
  public:
    bool flag(map<char, int>& mp) {
        for (auto& e : mp) {
            if (e.second > 0)
                return false;
        }
        return true;
    }
    string minWindow(string S, string T) {
        // write code here
        if(S.size()<T.size())return string("");
        map<char, int> mp;
        for (auto& e : T) {    // 使用map存储每一个T中字符
            mp[e]++;
        }
        int left = 0, right = 0;
        if(mp.find(S[left])!=mp.end())    // 如果首字符出现在map中则--;
            mp[S[left]]--;
        int pos = 0, res = 10001;
        while(right < S.size())
        {
            if(!flag(mp))
            {
                right++;    // 窗口多了一个元素,对其进行处理
                if(mp.find(S[right])!=mp.end())
                {
                    mp[S[right]]--;
                }
            }
            else
            {
                int len = right-left+1;    // left向后移动前对结果进行更新维护
                if(len < res)
                {
                    pos = left;
                    res = len;
                }
                if(mp.find(S[left])!=mp.end())
                    mp[S[left]]++;
                left++;
            }
        }
        if(res == 10001)    // 使用一个10001来判断是否为有效元素
            return string("");
        string str = S.substr(pos, res);
        return str;
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值