76. Minimum Window Substring

本文介绍了一种在O(n)复杂度下寻找包含指定字符集的最短子字符串的方法。通过双指针技术和预处理技术实现,适用于字符串搜索相关问题。

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

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 emtpy string”“.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

    题目大意: 在给定字符串s中,找出长度最短的且包含t中所有字符的子字符串,难点在于要在O(n)下完成
    思路:需要借助两个指针表示字符串的头指针和尾指针。从原字符串开头开始,首先移动尾指针,一直到字符串包含所有字符,记录下当前子字符串长度。然后开始移动头指针,移到第一个使得子字符串无效(不再包含所有字符)时,跳出循环。重复上一步移动尾指针,直到遍历完s。

预处理很重要:这里用一个int[257]的数组来保存符合要求的字符串可能出现的字符的个数,因为ASCII字符最多256个。移动尾指针来达到满足条件的子字符串,移动头指针来获取当前最短且满足条件的子字符串

对于大部分找满足某些限制子符串的问题,一般都是通过使用hashmap和两个辅助指针来解决问题

    public static String minWindow(String S, String T) {

        int start = 0,end = 0,dist = Integer.MAX_VALUE,head=0;
        int count = T.length();
        int[] needCharCount = new int[257];
        //可以使用int[257]来进行预处理,ASCII字符最多256个
        char[] chS = S.toCharArray();
        char[] chT = T.toCharArray();
        for (char c: chT)
            needCharCount[c]++;

        while (end < S.length())
        {
            char cur = chS[end];
            if (needCharCount[cur] > 0)
                count--;
            needCharCount[cur]--;                           
            //每次都needCharCount[cur]--, 真正需要的字符计数最小为0,有重复会出现负数,比如窗口内有2个B,那么B的计数就会是-1,而不需要的字符计数会小于0

            end++;

            while (start<end && count == 0)
            {
                if (end - start< dist) {
                    head =start;          
                    //需要head当临时变量存储,start一直在往后删,这里需要记录满足条件的最后位置的start
                    dist = end - start;
                }

                needCharCount[chS[start]]++;
//这里每次都needCharCount[start]++,这里遍历的都是之前已经遍历过的,所以每次都++,并不会使得不需要的字符大于0.一旦需要的字符计数大于0,那么count+1,变成无效窗口
                if (needCharCount[chS[start]] >0) {
                    count++;
                }

                start++;

            }

        }



        return dist==Integer.MAX_VALUE? "":S.substring(head, head+dist);
    }
string minWindow(string s, string t) {
        vector<int> map(128,0);
        for(auto c: t) map[c]++;
        int counter=t.size(), begin=0, end=0, d=INT_MAX, head=0;
        while(end<s.size()){
            if(map[s[end++]]-->0) counter--; //in t
            while(counter==0){ //valid
                if(end-begin<d)  d=end-(head=begin);
                if(map[s[begin++]]++==0) counter++;  //make it invalid
            }  
        }
        return d==INT_MAX? "":s.substr(head, d);
    }

for most substring problem, we are given a string and need to find a substring of it which satisfy some restrictions. A general way is to use a hashmap assisted with two pointers. The template is given below.

int findSubstring(string s){
        vector<int> map(128,0);
        int counter; // check whether the substring is valid
        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++]]-- ?){  /* modify counter here */ }

            while(/* counter condition */){ 

                 /* update d here if finding minimum*/

                //increase begin to make it invalid/valid again

                if(map[s[begin++]]++ ?){ /*modify counter here*/ }
            }  

            /* update d here if finding maximum*/
        }
        return d;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值