Code Logo

Minimum Window Substring

Published at25 Jul 2026
Hard 0 views
Like0

Given two strings s and t, find the minimum contiguous substring (window) of s that contains all the characters of t, including duplicates. If no such window exists, return an empty string.

Use a two-pointer sliding window approach with a hash map to track character frequencies. First, build a frequency map of characters in t. Then expand the right pointer to include characters until the window contains all required characters. Once valid, shrink from the left to find the minimum window.

Track the number of unique characters satisfied by a counter. When the counter reaches the number of unique required characters, the window is valid. Record the window length and start position when a smaller valid window is found.

Time complexity is O(n + m) where n is the length of s and m is the length of t. Each character is visited at most twice (once by right pointer, once by left pointer). Space is O(k) where k is the number of unique characters in t (at most 52 for letters, constant).

This is a classic sliding window problem that demonstrates the expand-contract pattern. The key insight is using a counter of satisfied requirements rather than checking all characters on each iteration.

Example Input & Output

Example 1
Input
"ab","a"
Output
"a"
Explanation

Single character window

Example 2
Input
"ADOBECODEBANC","ABC"
Output
"BANC"
Explanation

Minimum window containing A,B,C is BANC

Example 3
Input
"abcabdebac","cda"
Output
"cabd"
Explanation

Window cabd contains c,d,a

Example 4
Input
"a","aa"
Output
""
Explanation

Not enough characters in s

Example 5
Input
"a","a"
Output
"a"
Explanation

Single character match

Algorithm Flow

Recommendation Algorithm Flow for Minimum Window Substring
Recommendation Algorithm Flow for Minimum Window Substring

Solution Approach

Find the minimum window in string s that contains all characters of string t. Use the sliding window expand-contract pattern. Build a frequency map of characters needed. Expand the right pointer to include characters until all of t is covered. Then contract the left pointer to minimize the window while maintaining coverage. Track the minimum window length and start position.

function minWindow(s, t) {
  var need = {}, have = {}, match = 0, unique = 0;
  var left = 0, minLen = Infinity, minStart = 0;
  for (var i = 0; i < t.length; i++) need[t[i]] = (need[t[i]] || 0) + 1;
  unique = Object.keys(need).length;
  for (var right = 0; right < s.length; right++) {
    var c = s[right];
    have[c] = (have[c] || 0) + 1;
    if (have[c] === need[c]) match++;
    while (match === unique) {
      if (right - left + 1 < minLen) { minLen = right - left + 1; minStart = left; }
      var leftChar = s[left];
      if (have[leftChar] === need[leftChar]) match--;
      have[leftChar]--;
      left++;
    }
  }
  return minLen === Infinity ? '' : s.substring(minStart, minStart + minLen);
}

The match count tracks how many distinct characters have met their required frequency. Only when all characters match is the window valid. The inner while loop shrinks the window as much as possible while maintaining validity.

Time complexity is O(n), space complexity is O(k).

Best Answers

java
class Solution {
    public String solution(String s, String t) {
        if (s == null || t == null || s.length() == 0 || t.length() == 0) return "";
        int[] need = new int[128];
        for (int i = 0; i < t.length(); i++) need[t.charAt(i)]++;
        int missing = 0;
        for (int i = 0; i < 128; i++) if (need[i] > 0) missing++;
        int left = 0, start = 0, minLen = Integer.MAX_VALUE;
        for (int right = 0; right < s.length(); right++) {
            char rc = s.charAt(right);
            need[rc]--;
            if (need[rc] == 0) missing--;
            while (missing == 0) {
                if (right - left + 1 < minLen) {
                    minLen = right - left + 1;
                    start = left;
                }
                char lc = s.charAt(left);
                need[lc]++;
                if (need[lc] > 0) missing++;
                left++;
            }
        }
        return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);
    }
}