leetcode76. 最小覆盖子串

这篇博客讨论了一种使用哈希表和滑动窗口算法来解决LeetCode上的最小覆盖子串问题的方法。代码通过维护一个滑动窗口,并在窗口内检查目标字符串的所有字符是否都出现,从而找到包含目标字符串所有字符的最小子串。文章还提供了两种优化过的实现方式,提高了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题意:

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

注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

方法:哈希表+滑动窗口

class Solution {
public:
    string minWindow(string s, string t) {
        string ret="";//返回字符串
        unordered_map<char,int> mp;//哈希表
        int minL=s.size();//最短的长度初始化为s的size
        int left=0,right=0,diff=0;//滑动窗口左侧坐标,滑动窗口右侧坐标,字符总数
        int pos = 0;//最优的左侧位置

        //存哈希表,记录下t中的字符总数
        for(auto &ch:t)
        {
            mp[ch]++;
            diff++;
        }

        //窗口滑动
        while(right<s.size())//滑动窗口右侧没到终点时就不停
        {
            if(mp.find(s[right])!=mp.end())//如果当前字符s[right]在哈希表中找到了
            {
                mp[s[right]]--;//key值为s[right]对应的value值减1
                if(mp[s[right]]>=0)//如果减完以后还是正的,字符数减1
                    diff--;
            }
            while(diff==0)//假如字符数为0,就说明都找到了,滑动窗口左侧开始滑动
            {
                if(minL>right-left)//更新一下最短的长度
                {
                    minL=right-left;
                    pos = left;
                }
                if(mp.find(s[left])!=mp.end())//如果这个字符在哈希表中
                {
                    mp[s[left]]++;//key值为s[left]对应的value值加1
                    if(mp[s[left]]>0)//如果加完以后对应的value值大于0,字符数就加1
                        diff++;
                }
                left++;//滑动
            }
            right++;//滑动
        }
        if(pos==0&&minL==s.size()) return ret;
        ret=s.substr(pos,minL+1);
        return ret;
    }
};

代码优化:

class Solution {
public:
    string minWindow(string s, string t) {
        int minV = -100000;//定义最小值
        int len = s.size();//s字符串的长度
        int right=0,left=0,pos=0,minL=len,diff=t.size();//滑动窗口右侧坐标,滑动窗口左侧坐标,起始位置坐标,最短长度,不同的字符数量
        vector<int> mp(127,minV);//哈希表,<字符,出现次数>
        for(auto& ch:t)
        {
            if(mp[ch]==minV)//第一次出现,先更新初始值
                mp[ch]=0;
            mp[ch]++;//更新哈希表    
        }
        while(right<len)//限定滑动窗口移动的极限
        {
            if(mp[s[right]]!=minV)//对应的字符在t中
            {
                mp[s[right]]--;//更新哈希表
                if(mp[s[right]]>=0)//当对应的value值小于0时不再自减
                    diff--;//不同的字符数量减1
            }
            while(diff==0)//有差异的字符数目为0
            {
                if(minL>right-left)//更新最短长度和起始位置
                {
                    minL = right-left;
                    pos = left;
                }
                if(mp[s[left]]!=minV)//对应的字符在t中
                {
                    mp[s[left]]++;//更新哈希表
                    if(mp[s[left]]>0)
                        diff++;//不同的字符数量减1
                }
                left++;//滑动窗口左侧坐标右移
            }
            right++;//滑动窗口右侧坐标右移
        }
        if(pos==0&&minL==len) return "";//如果没找到,返回空值
        return s.substr(pos,minL+1);//否则返回这个子串
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值