【数组】LeetCode76-最小覆盖子串-滑动窗口

【数组】LeetCode76-最小覆盖子串-滑动窗口_第1张图片

 public String minWindow(String s, String t) {
        HashMap<Character, Integer> window = new HashMap<Character, Integer>(); // 记录窗口中每个字符对应出现的次数
        HashMap<Character, Integer> need = new HashMap<Character, Integer>();// 记录t需要出现的字符
        // 初始化两个窗口
        for (int i = 0; i < t.length(); i++) {
            char a=t.charAt(i);
            if(need.containsKey(a)){
                need.replace(a,need.get(a)+1);
            }else
                need.put(a,1);
            window.put(a,0);
        }
        int left=0; //左窗口 [ left
        int right=0; //右窗口 right )
        int valid=0;//表示need中有多少个字符已经满足要求
        int start=0;
        int len=Integer.MAX_VALUE;
        while (right<s.length()){
            char c=s.charAt(right);//c表示新加入窗口的字符(注意right是开区间)
            right++;
            if(need.containsKey(c)){//如果c是需要寻找的字符
                window.replace(c,window.get(c)+1);//可以放入window中
                if(window.get(c).equals(need.get(c))){
                    valid++;
                }
            }
            while (valid==need.size()){ //说明此时可以缩小窗口
                //更新最小覆盖串
                if(right-left<len){
                    start=left;
                    len=right-left;
                }
                char d=s.charAt(left); // d是将移出窗口的字符
                left++; // 缩小窗口
                if(need.containsKey(d)){
                    if(window.get(d).equals(need.get(d))) {
                        valid--; //缩小到只剩下一个时就不再满足条件了,继续移动right
                    }
                    window.replace(d,window.get(d)-1);
                }
            }
        }
        if(len==Integer.MAX_VALUE)
            return "";
        else
            return s.substring(start,start+len);//为什么这里不直接写left,right呢
   
    }

  • 如果当前字符不在need中,直接向前移动;
  • 如果当前字符在need中,首先更新窗口中的字符个数(+1);如果窗口中的该字符个数,与需要的字符个数相等,valid+1,表示已经有一个字符达到了要求。
  • 当valid和need的大小相等时,说明所有的字符个数都已经达到需要的个数了(或者多于需要的个数)。此时可以缩小窗口。
  • 缩小窗口时,如果当前字符不在need中,直接缩小。
  • 如果当前字符在need中,且窗口中的该字符个数与需要的字符个数相等,valid-1;然后更新窗口中的字符个数(-1)
  • 注意第二步和第四步的操作是对称的。

【数组】LeetCode76-最小覆盖子串-滑动窗口_第2张图片

【数组】LeetCode76-最小覆盖子串-滑动窗口_第3张图片

  • 注意返回应该是start到start+len,而不是left和right。这是因为,在取了字符之后,left和right都是马上更新的,也就是说当跳出循环时,left和right都可能已经处于下一个状态了。

【数组】LeetCode76-最小覆盖子串-滑动窗口_第4张图片

你可能感兴趣的:(#,数组,java)