leetcode76 Minimum Window Substring滑动窗口

https://leetcode.com/problems/minimum-window-substring/

题目大意:给定一个字符串S,和一个字符串T,求S的一个子串,包含T的所有字符,且子串最小。

我们应用滑动窗口的思想,首先我们知道包含T的所有字符,最小的子串一定以T的字符开头以T的字符结尾。两个指针l和r,表示滑动窗口的两端,我们举个例子:

S="ADOBECODEBANC"     T="ABC"

建立这样的一个数据结构map<char,int> ump初始为:

A:1

B:1

C:1

语义为A缺少一个,B缺少一个,C缺少一个

设定一个变量sum初始为3,表示总共缺少3个字符,当sum=0的时候表示S的子串包含ABC

l=0,r=0,ump= A:0,B:1,C:1,sum=2

r往右走,走到字符B,ump=A:0,B:0,C:1,sum=1,

r继续往右走,走到字符C,ump=A:0,B:0,C:0,sum=0此时是包含T所有字符的子串了。

l往后走,走到下一个T的字符B,ump=A:1,B:0,C:0,sum=1

r再往后走,走到字符B,此时ump=A:1,B:-1,C:0,sum=1(B多了一个,但是总共还是缺少一个字符A)

然后以此类推走下去,遍历过一次后,找到最小的子串。

#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
    string minWindow(string s, string t) {
        if(t.size()==0 || s.size()==0) return "";
        int l=0,r=-1;
        int min_l=0,min_r=INT_MAX-5;
        int sum=(int)t.size();
        unordered_map<char,int> ump;
        
        for(auto it=t.begin();it!=t.end();++it) ++ump[*it];
        
        for(;l<(int)s.size() && ump.find(s[l])==ump.end();++l);
        for(;l<(int)s.size() && r<(int)s.size();){
            //cout<<"l="<<l<<"  r="<<r<<"  sum="<<sum<<endl;
            
            while(r<(int)s.size() && sum!=0){
                ++r;
                
                //s[r]字符不在t中
                if(ump.find(s[r])!=ump.end()){
                    if(ump[s[r]]>0) --sum;
                    --ump[s[r]];
                    if(sum==0){
                        if(min_r-min_l+1>r-l+1){
                            min_l=l;
                            min_r=r;
                            //cout<<"update,min_l="<<min_l<<"  min_r="<<min_r<<endl;
                        }
                        break;
                    }
                }
            }
            
            //cout<<"mid,l="<<l<<"  r="<<r<<"  sum="<<sum<<endl;
            
            //l往右
            ++ump[s[l]];
            if(ump[s[l]]>0) ++sum;
            ++l;
            while(l<(int)s.size() && ump.find(s[l])==ump.end()) ++l;
            if(sum==0 && min_r-min_l+1>r-l+1){
                //cout<<"update,min_l="<<min_l<<"  min_r="<<min_r<<endl;
                min_l=l;
                min_r=r;
            }
        }
        
        //cout<<"min_l="<<min_l<<"  min_r="<<min_r<<endl;
        //cout<<"result=";
        //for(int i=min_l;i<=min_r;++i) cout<<s[i];
        //cout<<endl;
        
        if(min_r==INT_MAX-5) return "";
        else{
            string ret(s,min_l,min_r-min_l+1);
            return ret;
        }
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值