76. Minimum Window Substring (sliding window)

use two pointers (sliding window)

T :O(m+n)

S: O(|target|+|source|)

class Solution {
    public String minWindow(String s, String t) {
        int n = s.length();
        Map<Character, Integer> sCounter = new HashMap<>(); // char, count
        Map<Character, Integer> tCounter = new HashMap<>(); // char, count
        
        // record target char, freq
        for (char c : t.toCharArray()) {
            tCounter.put(c, tCounter.getOrDefault(c, 0)+1);
        }

        int end = 0;
        int charMatchedNum = 0;
        int resStart = 0;
        int resLen = Integer.MAX_VALUE; // for mini len result
        for (int start = 0; start < n; start++) {
            while (end < n && charMatchedNum < tCounter.size()) {
                char c = s.charAt(end);
                sCounter.put(c, sCounter.getOrDefault(c, 0)+1); // record source char, freq
                
                // needs integer to int, unboxing not work
                if ((int)sCounter.get(c) == (int)tCounter.getOrDefault(c,0)) { // if char freq equals, find matched
                    charMatchedNum++;
                }
                end++;
            }

            if (charMatchedNum == tCounter.size()) { // if matched count == target freq count, can get a result
                if (resLen > end - start) { // but we want mini len of result
                    resStart = start; // result's start index
                    resLen = end - start; // result's len
                }
            }
            
            char c = s.charAt(start);
            sCounter.put(c, sCounter.getOrDefault(c,0)-1); // out of the start index loop, 
            
            // ๅฆ‚ๆžœๅ…ฉ่€…ๆธ›1ๅพŒ, ็›ธ็ญ‰, matched countๆ‡‰่ฉฒ --
            if ((int)sCounter.get(c) == (int)(tCounter.getOrDefault(c,0) - 1)) { 
                charMatchedNum--;
            }
        }
        // ๅฆ‚ๆžœ resLen ้‚„ๆ˜ฏๆœ€ๅคงๅ€ผ, ไปฃ่กจๆ‰พไธๅˆฐ
        return resLen == Integer.MAX_VALUE ? "" : s.substring(resStart, resStart + resLen);
    }
}

T: O(n)
S: O(n)
class Solution {
    public String minWindow(String s, String t) {
        if (t.length() > s.length()) {
            return "";
        }
        
        int len = Integer.MAX_VALUE;
        int left = 0;
        int right = 0;
        int start = 0;
        
        Map<Character, Integer> needs = new HashMap<>();
        int matched = 0;
        for (char c : t.toCharArray()) {
            needs.put(c, needs.getOrDefault(c, 0)+1);
        }
        
        while (right < s.length()) {
            char rightChar = s.charAt(right);
            right++;
            if (needs.containsKey(rightChar)) {
                needs.put(rightChar, needs.getOrDefault(rightChar, 0)-1);
                if (needs.get(rightChar) == 0) {
                    matched++;
                }
            }
            while (matched == needs.size()) {
                if (right - left < len) {
                    start = left;
                    len = right - left;
                }
                
                char leftChar = s.charAt(left);
                left++;
                if (needs.containsKey(leftChar)) {
                    if (needs.get(leftChar) == 0) {
                        matched--;
                    }
                    needs.put(leftChar, needs.getOrDefault(leftChar, 0)+1);
                }
            }
        }

        return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len);
    }
}
/*
build a t map
compare in s, s map record in this window, do we have t map count
s = "ADOBECODEBANC", t = "ABC"
      l
          r
          
          when we have all valid count, start to shrink left, 
          update min len, record start point(left) -> right - left
          until not valid number
          
          count must be the same (or "aa" , "aa", the ans -> "a" only one)
          
          at last, just use one map, to save needs count first,
          then using subtraction (if current char == needs word, subtrct needs count), when needs == 0, matched++
          if matched == needs.size() it means we have find matched substring contains all needs words (t)
          
          T: O(n)
          S: O(n)
*/

Last updated