Problem Description
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
Example 1: Input: s = "ADOBECODEBANC", t = "ABC" Output: "BANC" Explanation: The minimum window substring "BANC" includes 'A', 'B', and 'C' from string t. Example 2: Input: s = "a", t = "a" Output: "a" Explanation: The entire string s is the minimum window. Example 3: Input: s = "a", t = "aa" Output: "" Explanation: Both 'a's from t must be included in the window. Since the largest window of s only has one 'a', return empty string.
Python Solution
def minWindow(s: str, t: str) -> str:
if not s or not t:
return ""
# Initialize dictionaries
t_count = {}
window = {}
for char in t:
t_count[char] = t_count.get(char, 0) + 1
window[char] = 0
# Initialize variables
required = len(t_count)
formed = 0
left = right = 0
min_len = float('inf')
min_window = ""
while right < len(s):
# Add one character from the right
char = s[right]
if char in t_count:
window[char] += 1
if window[char] == t_count[char]:
formed += 1
# Contract window from the left
while formed == required and left <= right:
# Update minimum window
if right - left + 1 < min_len:
min_len = right - left + 1
min_window = s[left:right + 1]
# Remove leftmost character
char = s[left]
if char in t_count:
window[char] -= 1
if window[char] < tCount[char]:
formed -= 1
left += 1
right += 1
return min_window
Java Solution
class Solution {
public String minWindow(String s, String t) {
if (s == null || t == null || s.length() == 0 || t.length() == 0) {
return "";
}
// Initialize frequency maps
Map tCount = new HashMap<>();
Map window = new HashMap<>();
for (char c : t.toCharArray()) {
tCount.put(c, tCount.getOrDefault(c, 0) + 1);
}
// Initialize variables
int required = tCount.size();
int formed = 0;
int left = 0, right = 0;
int minLen = Integer.MAX_VALUE;
int minLeft = 0, minRight = 0;
while (right < s.length()) {
// Add one character from the right
char c = s.charAt(right);
window.put(c, window.getOrDefault(c, 0) + 1);
if (tCount.containsKey(c) && window.get(c).equals(tCount.get(c))) {
formed++;
}
// Contract window from the left
while (formed == required && left <= right) {
// Update minimum window
if (right - left + 1 < minLen) {
minLen = right - left + 1;
minLeft = left;
minRight = right;
}
// Remove leftmost character
char leftChar = s.charAt(left);
window.put(leftChar, window.get(leftChar) - 1);
if (tCount.containsKey(leftChar) &&
window.get(leftChar) < tCount.get(leftChar)) {
formed--;
}
left++;
}
right++;
}
return minLen == Integer.MAX_VALUE ? "" :
s.substring(minLeft, minRight + 1);
}
}
C++ Solution
class Solution {
public:
string minWindow(string s, string t) {
if (s.empty() || t.empty()) {
return "";
}
// Initialize frequency maps
unordered_map tCount;
unordered_map window;
for (char c : t) {
tCount[c]++;
}
// Initialize variables
int required = tCount.size();
int formed = 0;
int left = 0, right = 0;
int minLen = INT_MAX;
int minLeft = 0;
while (right < s.length()) {
// Add one character from the right
char c = s[right];
window[c]++;
if (tCount.count(c) && window[c] == tCount[c]) {
formed++;
}
// Contract window from the left
while (formed == required && left <= right) {
// Update minimum window
if (right - left + 1 < minLen) {
minLen = right - left + 1;
minLeft = left;
}
// Remove leftmost character
char leftChar = s[left];
window[leftChar]--;
if (tCount.count(leftChar) &&
window[leftChar] < tCount[leftChar]) {
formed--;
}
left++;
}
right++;
}
return minLen == INT_MAX ? "" :
s.substr(minLeft, minLen);
}
};
JavaScript Solution
/**
* @param {string} s
* @param {string} t
* @return {string}
*/
var minWindow = function(s, t) {
if (!s || !t) {
return "";
}
// Initialize frequency maps
const tCount = new Map();
const window = new Map();
for (let char of t) {
tCount.set(char, (tCount.get(char) || 0) + 1);
}
// Initialize variables
const required = tCount.size;
let formed = 0;
let left = 0, right = 0;
let minLen = Infinity;
let minWindow = "";
while (right < s.length) {
// Add one character from the right
let char = s[right];
window.set(char, (window.get(char) || 0) + 1);
if (tCount.has(char) && window.get(char) === tCount.get(char)) {
formed++;
}
// Contract window from the left
while (formed === required && left <= right) {
// Update minimum window
if (right - left + 1 < minLen) {
minLen = right - left + 1;
minWindow = s.slice(left, right + 1);
}
// Remove leftmost character
let leftChar = s[left];
window.set(leftChar, window.get(leftChar) - 1);
if (tCount.has(leftChar) &&
window.get(leftChar) < tCount.get(leftChar)) {
formed--;
}
left++;
}
right++;
}
return minWindow;
};
C# Solution
public class Solution {
public string MinWindow(string s, string t) {
if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(t)) {
return "";
}
// Initialize frequency dictionaries
Dictionary tCount = new Dictionary();
Dictionary window = new Dictionary();
foreach (char c in t) {
if (!tCount.ContainsKey(c)) tCount[c] = 0;
tCount[c]++;
}
// Initialize variables
int required = tCount.Count;
int formed = 0;
int left = 0, right = 0;
int minLen = int.MaxValue;
int minLeft = 0, minRight = 0;
while (right < s.Length) {
// Add one character from the right
char c = s[right];
if (!window.ContainsKey(c)) window[c] = 0;
window[c]++;
if (tCount.ContainsKey(c) && window[c] == tCount[c]) {
formed++;
}
// Contract window from the left
while (formed == required && left <= right) {
// Update minimum window
if (right - left + 1 < minLen) {
minLen = right - left + 1;
minLeft = left;
minRight = right;
}
// Remove leftmost character
char leftChar = s[left];
window[leftChar]--;
if (tCount.ContainsKey(leftChar) &&
window[leftChar] < tCount[leftChar]) {
formed--;
}
left++;
}
right++;
}
return minLen == int.MaxValue ? "" :
s.Substring(minLeft, minRight - minLeft + 1);
}
}
Complexity Analysis
- Time Complexity: O(|S| + |T|) where |S| and |T| are the lengths of strings s and t
- Space Complexity: O(|T|) to store the character frequency maps
Solution Explanation
This solution uses the sliding window technique with two pointers:
- Key concept:
- Use two pointers to maintain a window
- Track character frequencies
- Expand and contract window as needed
- Algorithm steps:
- Initialize frequency maps for target string
- Expand window until valid substring found
- Contract window to minimize length
- Track minimum window seen so far
Key points:
- Efficient sliding window approach
- Handles duplicates correctly
- Maintains minimum window size
- Returns empty string if no solution