Leetcode76. Minimum Window Substring | Hard | Sliding Window

Time: O(n)
Space: O(n)

双指针/滑动窗口其实关键的都是想清楚左右边界要怎么移动。这道题动的感觉有点像队列但不太一样。
第一步要想到把t转化成map。因为t的字母在s里的顺序是没有要求的,相当于是对单个字符查验,想到这里就很容易想到要用map存(因为题目也说了可能t会有重复的字母)。
在s里匹配的时候,很容易想到最暴力的做法,就是n:s.length()为开始,然后往后找直到找全t里的所有字母。首先从n=0开始,找齐之后是窗口的初始位置。此时是没必要往后继续的,因为题目要的是最短。假如我们是最简单粗暴的暴力,那么接下来就是n=1,一直往后直到找齐。这里仔细思考一下,就能想到其实s[0]是有两种情况的,s[0]是t的字母或者不是。假如s[0]不是t的字母,那它其实删掉了也不影响剩下部分满足条件。假如s[0]是t的字母,那么此时从n=1开始,t的字母就是不全的,需要继续向后直到找全。
其实如果不是这题tag写了滑动窗口,感觉还是挺难想的。但如果一开始就知道是滑动窗口,做的时候其实关注点就是确定了窗口的初始位置之后,左右该分别如何移动。这题的切入点其实就是s[0]的两种情况,因为题目要求是找最小,所以容易想到肯定是左右没用的字母都划掉才是我们要的答案。
所以移动方式应该是:从left=0开始,right先不断后移找齐所有字母。之后,left右移一位,如果Left是t的字母,则right继续右移直到再次找齐。若left不是,则left继续移动直到它是t的字母。结束条件就是left走到了最后(或者其实应该是left < s.length()-t.length() )
特殊情况:s<t,直接返回““

涉及到java的hashmap操作和string操作比较多。
1.string的substring(index1, index2)截取的时候,是不包含index2的,所以这里要+1
2.hashmap的replace操作,最好有个中间变量。不然就会出各种奇怪的错……看了半天也没明白是啥🚬

class Solution {
    public String minWindow(String s, String t) {
        if(s.length()<t.length()) return "";
        
        HashMap<Character, Integer> T = new HashMap<Character, Integer>();
        HashMap<Character, Integer> WindowMap = new HashMap<Character, Integer>();
        
        int Tcnt = 0, Wcnt = 0, ans = 100001;
        String strans = new String();
        
        // convert t to map
        for(int i = 0;i<t.length();i++){
            if(T.containsKey(t.charAt(i))){
                int tmp = T.get(t.charAt(i));
                T.replace(t.charAt(i), tmp+1);
            }
            else            
                T.put(t.charAt(i), 1);
            Tcnt++;
        }
        
        // create window map
        for(char iter:T.keySet()){
            // System.out.println(iter);
            WindowMap.put(iter, 0);
        }
        
        int left = 0, right = 0;
        if(WindowMap.containsKey(s.charAt(0))){
            if(WindowMap.get(s.charAt(0)) < T.get(s.charAt(0)))
                Wcnt++;
            WindowMap.replace(s.charAt(0), 1);
        }
        
        while(left < s.length()){
            while(Wcnt < Tcnt){
                right++;
                if(right >= s.length()) 
                    break;
                if(WindowMap.containsKey(s.charAt(right))){
                    int tmpk = WindowMap.get(s.charAt(right));
                    if(tmpk < T.get(s.charAt(right)))
                        Wcnt++;
                    WindowMap.replace(s.charAt(right), tmpk+1);
                }
            }
            
            // System.out.println("left "+left+" right "+right+" Wcnt "+Wcnt+" Tcnt "+Tcnt+" ans "+strans);
            int tmplen = right-left+1;
            if((Wcnt == Tcnt) && (tmplen < ans)){
                ans = tmplen;
                strans = s.substring(left, right+1);
            }
            if(WindowMap.containsKey(s.charAt(left))){
                int tmpx = WindowMap.get(s.charAt(left));
                if(tmpx == T.get(s.charAt(left)))
                    Wcnt--;
                WindowMap.replace(s.charAt(left), tmpx-1);
            }
            left++;
        }
        return strans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值