Skip to content
AI360Xpert
Back to Sliding Window
Hard

Minimum Window Substring

Given two strings `s` and `t` of lengths `m` and `n` respectively, return the minimum window substring of `s` such that every character in `t` (including duplicates) is included in the window. If there is no such substring, return the empty string `""`. The testcases will be generated such that the answer is unique.

Examples

Input:s = "ADOBECODEBANC", t = "ABC"
Output:"BANC"
The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t.
Input:s = "a", t = "a"
Output:"a"
The entire string s is the minimum window.

Constraints

  • m == s.length
  • n == t.length
  • 1 <= m, n <= 10^5
  • s and t consist of uppercase and lowercase English letters.

Sliding Window with Target Frequencies

Approach

First, count frequencies of characters in `t`. Use a sliding window on `s`, tracking character frequencies in the current window. Keep a `have` count (characters that meet frequency requirement) and `need` count (total unique characters in `t`). When `have == need`, the window is valid. Shrink the window from the left while it remains valid to find the minimum length, updating the best result.

Complexity Analysis

Time Complexity
O(m + n)
Space Complexity
O(1)

Space is bounded by the size of the character set (e.g., 52 for English letters), thus effectively O(1).

Solution.java
class Solution {    public String minWindow(String s, String t) {        if (s.isEmpty() || t.isEmpty() || s.length() < t.length()) return "";                Map<Character, Integer> countT = new HashMap<>();        for (char c : t.toCharArray()) {            countT.put(c, countT.getOrDefault(c, 0) + 1);        }                int have = 0, need = countT.size();        Map<Character, Integer> window = new HashMap<>();                int left = 0;        int minLen = Integer.MAX_VALUE;        int[] minSpan = {-1, -1}; // [start, end]                for (int right = 0; right < s.length(); right++) {            char c = s.charAt(right);            window.put(c, window.getOrDefault(c, 0) + 1);                        if (countT.containsKey(c) && window.get(c).equals(countT.get(c))) {                have++;            }                        while (have == need) {                // Update result if smaller window found                if ((right - left + 1) < minLen) {                    minLen = right - left + 1;                    minSpan[0] = left;                    minSpan[1] = right;                }                                // Pop from the left                char leftChar = s.charAt(left);                window.put(leftChar, window.get(leftChar) - 1);                                if (countT.containsKey(leftChar) && window.get(leftChar) < countT.get(leftChar)) {                    have--;                }                left++;            }        }                return minLen == Integer.MAX_VALUE ? "" : s.substring(minSpan[0], minSpan[1] + 1);    }}