from collections import Counter
class Solution:
def minWindow(self, s: str, t: str) -> str:
if not t or not s:
return ""
dict_t = Counter(t)
required = len(dict_t)
l, r = 0, 0
formed = 0
window_counts = {}
ans = float("inf"), None, None
while r < len(s):
character = s[r]
window_counts[character] = window_counts.get(character, 0) + 1
if character in dict_t and window_counts[character] == dict_t[character]:
formed += 1
while l <= r and formed == required:
character = s[l]
if r - l + 1 < ans[0]:
ans = (r - l + 1, l, r)
window_counts[character] -= 1
if character in dict_t and window_counts[character] < dict_t[character]:
formed -= 1
l += 1
r += 1
return "" if ans[0] == float("inf") else s[ans[1]:ans[2]+1]
#include <string>
#include <unordered_map>
#include <climits>
using namespace std;
class Solution {
public:
string minWindow(string s, string t) {
if (t.empty() || s.empty()) return "";
unordered_map<char, int> dict_t;
for (char c : t) dict_t[c]++;
int required = dict_t.size();
unordered_map<char, int> window_counts;
int l = 0, r = 0, formed = 0;
int min_len = INT_MAX, min_l = 0;
while (r < s.size()) {
char c = s[r];
window_counts[c]++;
if (dict_t.count(c) && window_counts[c] == dict_t[c]) {
formed++;
}
while (l <= r && formed == required) {
if (r - l + 1 < min_len) {
min_len = r - l + 1;
min_l = l;
}
char ch = s[l];
window_counts[ch]--;
if (dict_t.count(ch) && window_counts[ch] < dict_t[ch]) {
formed--;
}
l++;
}
r++;
}
return min_len == INT_MAX ? "" : s.substr(min_l, min_len);
}
};
import java.util.*;
class Solution {
public String minWindow(String s, String t) {
if (s.length() == 0 || t.length() == 0) return "";
Map<Character, Integer> dictT = new HashMap<>();
for (char c : t.toCharArray()) {
dictT.put(c, dictT.getOrDefault(c, 0) + 1);
}
int required = dictT.size();
Map<Character, Integer> windowCounts = new HashMap<>();
int l = 0, r = 0, formed = 0;
int[] ans = {-1, 0, 0};
while (r < s.length()) {
char c = s.charAt(r);
windowCounts.put(c, windowCounts.getOrDefault(c, 0) + 1);
if (dictT.containsKey(c) && windowCounts.get(c).intValue() == dictT.get(c).intValue()) {
formed++;
}
while (l <= r && formed == required) {
if (ans[0] == -1 || r - l + 1 < ans[0]) {
ans[0] = r - l + 1;
ans[1] = l;
ans[2] = r;
}
char ch = s.charAt(l);
windowCounts.put(ch, windowCounts.get(ch) - 1);
if (dictT.containsKey(ch) && windowCounts.get(ch).intValue() < dictT.get(ch).intValue()) {
formed--;
}
l++;
}
r++;
}
return ans[0] == -1 ? "" : s.substring(ans[1], ans[2] + 1);
}
}
var minWindow = function(s, t) {
if (!s || !t) return "";
let dictT = {};
for (let c of t) dictT[c] = (dictT[c] || 0) + 1;
let required = Object.keys(dictT).length;
let l = 0, r = 0, formed = 0;
let windowCounts = {};
let ans = [Infinity, 0, 0];
while (r < s.length) {
let c = s[r];
windowCounts[c] = (windowCounts[c] || 0) + 1;
if (dictT[c] && windowCounts[c] === dictT[c]) {
formed++;
}
while (l <= r && formed === required) {
if (r - l + 1 < ans[0]) {
ans = [r - l + 1, l, r];
}
let ch = s[l];
windowCounts[ch]--;
if (dictT[ch] && windowCounts[ch] < dictT[ch]) {
formed--;
}
l++;
}
r++;
}
return ans[0] === Infinity ? "" : s.slice(ans[1], ans[2] + 1);
};
s
and t
, find the minimum window substring in s
that contains all the characters from t
(including duplicates). The substring must be contiguous. If there is no such substring, return the empty string ""
.t
must appear in the window at least as many times as it appears in t
.s
can be reused as long as they are within the window; you do not "consume" them for t
.
Input: s = "ADOBECODEBANC", t = "ABC"
Output: "BANC"
s
to see if it contains all characters from t
. However, this brute-force method is inefficient, especially for long strings.s
that contains all the required characters. This hints at using a "sliding window" technique, where we expand and contract a window over s
to efficiently check for valid substrings.s
, expanding the window to include new characters and contracting it to remove unnecessary ones, always keeping track of the required characters from t
.
t
: Use a hash map to store the frequency of each character in t
. This lets us quickly check if our current window contains enough of each required character.
s
into the current window, updating counts as we go.
t
(with correct frequencies), try to shrink the window from the left to find the smallest possible valid window.
s = "ADOBECODEBANC"
, t = "ABC"
t
: {'A':1, 'B':1, 'C':1}s
: O(N2) substrings, each checked for O(M) (length of t
) characters → O(N2 * M) time.t
counts.s
. Each character is visited at most twice (once by right, once by left pointer).t
and the window).