双指针+哈希表类题目Longest Substring Without Repeating Charac Longest Substring Without Repeating Characters

76. Minimum Window Substring

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,
S = "ADOBECODEBANC"
T = "ABC"

Minimum window is "BANC".

Note:
If there is no such window in S that covers all characters in T, return the empty string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

class Solution {
public:
    string minWindow(string s, string t) {
        vector<int> map(128,0);//初始化map哈希表,全部为0
        //根据给定的T,将里面相应的子母在哈希表中计数为1
        for(int i=0;i<t.size();i++)
            map[t[i]]++;//t中出现的子母全部变成1
        //初始化双指针和计数、长度
        int start=0;//起始指针
        int end=0;//终止指针
        int count=t.size();//计数,初始化为模式字符串的长度
        int d=numeric_limits<int>::max();//初始化结果的长度为最大
        int head=0;//这个head当前找到满足要求的双指针范围中,出现的第一个在t中的字符位置,因为start会更新的
        //下面进行正式的遍历,只遍历一遍
        //首先考虑我们所期望的过程:从在s中找到第一个t中的子母开始,count--,直到找到最后一个t钟出现的字符,count变成0,当一个t中的字符找到之后,他的map计数值变成0,处理count语句应该只当map[i]==1的时候才减一。最后end指向当前最后一个子串的下一个位置。
        //找到子串之后,可能出现这种情况:因为start一直指向0位置,所以可能第一个符合要求的字符在0位置后面,现在的子串包含前面一段无用子串,需要设置循环,缩小到第一个满足要求的字符(t中的字符)。同时更新最小长度。跳出循环。
        while(end<s.size())
        {
            if(map[s[end++]]-->0) count--;
            /*if(map[s[end]]>0)
            {
                count--;//找到一个t中字符,count自减,然后将这个出现的字符map减1变成0
                map[s[end]]--;
                end++;
            }*///这种写法不行,因为加和-操作不管条件是否满足都要进行
            //简化版本: if(map[s[end++]]-->0) count--;
            while(count==0)//能够进入循环,说明目前end和start指向的区间范围,包含了所有的t中子母,这个时候end指向最后一个子母的下一个,这个循环不断的缩减长度,知道begin指向第一个出现的t字符,
            {
                if(end-start<d) d=end-(head=start);//只有在需要更新的时候才同时更新head
                
                if(map[s[start++]]++==0) count++;//这一段之前已经操作过一遍,由于t中的字符开始的时候大1,所以第一个等于0的一定是出现的第一个t中的字符,当找到t字符时,start指向第一个字符的下一个位置。end指向最后一个字符的下一个位置。之前最后一次计算的值正好是正确的长度
                //保存head的原因是,后面进入到外循环时,不一定再找到另外一个满足要求的字符串
                //下面在寻找另外一个字符串,这个时候count是1,只要找到另外一个之前之前start找到的字符即可(相当于把之前的那个字符舍弃了)
            }
            
        }
        return d==numeric_limits<int>::max()?"":s.substr(head,d);//有可能没找到
        
        
    }
};
整体思路:

int findSubstring(string s){
        vector<int> map(128,0);
        int counter; 
    //检查字符串是否是有效的 
        int begin=0, end=0; //two pointers, one point to tail and one  head
        int d; //the length of substring  子字符串长度

        for() { /* initialize the hash map here 初始化哈希表 */ }

        while(end<s.size()){

            if(map[s[end++]]-- ?){  /* 根据更新计数值*/ }

            while(/* 达到计数值条件*/){ 
                 
                 /* */

                //increase begin to make it invalid/valid again 
                
                if(map[s[begin++]]++ ?){ /*modify counter here*/ }
            }  

            /* update d here if finding maximum,最大值在外边进行*/
        }
        return d;
  }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值