19. Minimum Window Substring
Return the shortest substring of s that contains every character of t (including duplicates). If there is none, return "". The answer is unique when it exists.
Example 1
Input:
s = "ADOBECODEBANC", t = "ABC"Output:
"BANC"Explanation: “BANC” is the shortest window containing A, B and C.
Example 2
Input:
s = "a", t = "aa"Output:
""Explanation: Two a’s are needed but
s has only one.Hint 1
Expand right until the window covers t, then shrink from the left while it still covers t.
Hint 2
Track a single counter missing instead of comparing maps.
Approach 1: Every substring
Check all substrings for coverage.
⏱ Time O(n² · k)💾 Space O(k)
Approach 2: Expand / shrink window ✅
Need-counts plus a missing counter make each step O(1).
⏱ Time O(n + m)💾 Space O(k)
Reference solution for Expand / shrink window (time O(n + m), space O(k)). Each solution passes every test in all four languages.
class Solution:
def minWindow(self, s: str, t: str) -> str:
need = Counter(t)
missing = len(t) # characters of t still not covered
left = 0
best = (0, 0)
for right, ch in enumerate(s, 1): # window is s[left:right]
if need[ch] > 0:
missing -= 1
need[ch] -= 1
if missing == 0:
while need[s[left]] < 0: # drop characters we have spare
need[s[left]] += 1
left += 1
if best == (0, 0) or right - left < best[1] - best[0]:
best = (left, right)
need[s[left]] += 1 # give up the first needed char and keep looking
missing += 1
left += 1
return s[best[0]:best[1]]class Solution {
public String minWindow(String s, String t) {
int[] need = new int[128];
for (char c : t.toCharArray()) need[c]++;
int missing = t.length(), left = 0, bestL = 0, bestLen = Integer.MAX_VALUE;
for (int right = 0; right < s.length(); right++) {
if (need[s.charAt(right)]-- > 0) missing--;
while (missing == 0) {
if (right - left + 1 < bestLen) { bestLen = right - left + 1; bestL = left; }
if (++need[s.charAt(left++)] > 0) missing++; // window lost a needed char
}
}
return bestLen == Integer.MAX_VALUE ? "" : s.substring(bestL, bestL + bestLen);
}
}class Solution {
public:
string minWindow(string s, string t) {
vector<int> need(128, 0);
for (char c : t) need[c]++;
int missing = t.size(), left = 0, bestL = 0, bestLen = INT_MAX;
for (int right = 0; right < (int)s.size(); right++) {
if (need[s[right]]-- > 0) missing--;
while (missing == 0) {
if (right - left + 1 < bestLen) { bestLen = right - left + 1; bestL = left; }
if (++need[s[left++]] > 0) missing++; // window lost a needed char
}
}
return bestLen == INT_MAX ? "" : s.substr(bestL, bestLen);
}
};function minWindow(s, t) {
const need = new Map();
for (const c of t) need.set(c, (need.get(c) || 0) + 1);
let missing = t.length, left = 0, bestL = 0, bestLen = Infinity;
for (let right = 0; right < s.length; right++) {
const c = s[right];
if ((need.get(c) || 0) > 0) missing--;
need.set(c, (need.get(c) || 0) - 1);
while (missing === 0) {
if (right - left + 1 < bestLen) { bestLen = right - left + 1; bestL = left; }
const d = s[left++];
need.set(d, need.get(d) + 1);
if (need.get(d) > 0) missing++; // window lost a needed char
}
}
return bestLen === Infinity ? '' : s.slice(bestL, bestL + bestLen);
}Try solving it yourself first. Interviewers care more about how you explain the approach than about the finished code.
This problem is explained in the lesson Sliding Window.
Run your code to see results here.