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

一个抄袭的解答:

public class Solution {
    public String minWindow(String S, String T) {
        int map [] = new int[128];

        for(int i = 0; i < T.length(); i++){//这里我把T开始写成S了(我也把i从1开始了,那也是错的,从零开始是对),要明白我们在map里记载的是T里的字符是否存在。map就像一排的桶。图像记忆是王道!!!
            map[T.charAt(i)]++; 
        }
        int begin = 0, end = 0, d = Integer.MAX_VALUE, counter = T.length(), head = 0; 

        while(end < S.length()){
        //map是一排桶,它标记了T中存在的字符,现在我们用这些桶来检测S中的字符是否有和T中一样的,如果一样(map[S.charAt(end++)] -- > 0)我们就让计数器减一,这样等到计数器为零,我们就开始停下来,好好审视d(窗口)是否更小了些(我们要找到一个很小的窗口哦)
            if(map[S.charAt(end++)] -- > 0){
                counter--;
            }
            //停下来,好好审视d(窗口)是否更小了些(我们要找到一个很小的窗口哦)
            while(counter == 0){
                if(d > (end -begin)){
                    d = end - (head = begin);
                }
                if(map[S.charAt(begin ++)] ++ == 0){
                    counter ++;
                }
            }
        }
        return d == Integer.MAX_VALUE?"":S.substring(head,head + d);
    }
}

原答案

这道题的思路是:
1) begin开始指向0, end一直后移,直到begin - end区间包含T中所有字符。
记录窗口长度d
2) 然后begin开始后移移除元素,直到移除的字符是T中的字符则停止,此时T中有一个字符没被
包含在窗口,
3) 继续后移end,直到T中的所有字符被包含在窗口,重新记录最小的窗口d。
4) 如此循环知道end到S中的最后一个字符。
时间复杂度为O(n)

链接:https://www.nowcoder.com/questionTerminal/c466d480d20c4c7c9d322d12ca7955ac
来源:牛客网



public class Solution {
    public String minWindow(String S, String T) {
        int[] map = new int[128];
        //init map, 记录T中每个元素出现的次数
        for(int i = 0; i < T.length(); i++) {
            map[T.charAt(i)]++;
        }

        // begin end两个指针指向窗口的首位,d记录窗口的长度, counter记录T中还有几个字符没被窗口包含
        int begin = 0, end = 0, d = Integer.MAX_VALUE, counter = T.length(), head = 0;
        // end指针一直向后遍历
        while(end < S.length()) {
            // map[] > 0 说明该字符在T中出现,counter-- 表示对应的字符被包含在了窗口,counter--, 如果s中的字符没有在T中出现,则map[]中对应的字符-1后变为负值
            if(map[S.charAt(end++)]-- > 0) {
                counter--;
            }
            // 当counter==0时,说明窗口已经包含了T中的所有字符
            while (counter == 0) {
                if(end - begin < d) {
                    d = end - (head = begin);
                }
                if(map[S.charAt(begin++)]++ == 0) {  // begin开始后移,继续向后寻找。如果begin后移后指向的字符在map中==0,表示是在T中出现的,如果没有出现,map[]中的值会是负值。
                    counter++;                      // 在T中的某个字符从窗口中移除,所以counter++。
                }
            }
        }
        return d==Integer.MAX_VALUE ? "" :S.substring(head, head+d);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值