29. Smallest Window Containing All Characters
β GFG solution to the Smallest Window Containing All Characters problem: find minimum length substring containing all characters of pattern using sliding window technique. π
The problem can be found at the following link: π Question Link
π§© Problem Description
You are given two strings s
and p
. Your task is to find the smallest substring in s
that contains all characters (including duplicates) of the string p
. Return an empty string if no such substring exists.
If there are multiple substrings of the same minimum length, return the one with the least starting index.
π Examples
Example 1
Input: s = "timetopractice", p = "toc"
Output: "toprac"
Explanation: "toprac" is the smallest substring in which "toc" can be found.
Example 2
Input: s = "zoomlazapzo", p = "oza"
Output: "apzo"
Explanation: "apzo" is the smallest substring in which "oza" can be found.
Example 3
Input: s = "zoom", p = "zooe"
Output: ""
Explanation: No substring is present containing all characters of p.
π Constraints
$1 \le \text{s.length()}, \text{p.length()} \le 10^6$
s
,p
consists of lowercase english letters
β
My Approach
The optimal approach uses the Sliding Window technique with Frequency Arrays to efficiently find the minimum window containing all pattern characters:
Sliding Window + Frequency Tracking
Initialize Frequency Arrays:
Create frequency array for pattern
p
to store required character counts.Create window frequency array to track characters in current window.
Calculate total unique characters required from pattern.
Expand Window:
Move
right
pointer and adds[right]
to window frequency.If character frequency matches required frequency, increment
formed
counter.
Contract Window:
When all required characters are formed, try to minimize window size.
Move
left
pointer forward while maintaining validity.Update minimum window if current window is smaller.
Track Optimal Window:
Store the starting position and length of the smallest valid window.
Continue until
right
pointer reaches end of string.
Return Result:
Return the substring of minimum length, or empty string if no valid window exists.
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(|s| + |p|), where |s| and |p| are the lengths of strings s and p respectively. Each character in s is visited at most twice (once by right pointer and once by left pointer), and we process pattern p once for frequency calculation.
Expected Auxiliary Space Complexity: O(1), as we use fixed-size arrays of length 256 (constant space for ASCII characters) regardless of input size.
π§βπ» Code (C++)
class Solution {
public:
string smallestWindow(string &s, string &p) {
int m = s.size(), n = p.size();
if (m < n) return "";
int freq[256] = {0}, window[256] = {0};
for (char c : p) freq[c]++;
int formed = 0, required = 0;
for (int i = 0; i < 256; i++) if (freq[i] > 0) required++;
int l = 0, r = 0, minLen = INT_MAX, minStart = 0;
while (r < m) {
window[s[r]]++;
if (freq[s[r]] > 0 && window[s[r]] == freq[s[r]]) formed++;
while (l <= r && formed == required) {
if (r - l + 1 < minLen) {
minLen = r - l + 1;
minStart = l;
}
window[s[l]]--;
if (freq[s[l]] > 0 && window[s[l]] < freq[s[l]]) formed--;
l++;
}
r++;
}
return minLen == INT_MAX ? "" : s.substr(minStart, minLen);
}
};
β Code (Java)
class Solution {
public static String smallestWindow(String s, String p) {
int m = s.length(), n = p.length();
if (m < n) return "";
int[] need = new int[256];
for (char c : p.toCharArray()) need[c]++;
int missing = n, start = 0, minStart = 0, minLen = Integer.MAX_VALUE;
for (int end = 0; end < m; end++) {
if (need[s.charAt(end)]-- > 0) missing--;
while (missing == 0) {
if (end - start + 1 < minLen) {
minLen = end - start + 1;
minStart = start;
}
if (++need[s.charAt(start++)] > 0) missing++;
}
}
return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLen);
}
}
π Code (Python)
class Solution:
def smallestWindow(self, s, p):
m, n = len(s), len(p)
if m < n: return ""
need = [0] * 256
for c in p: need[ord(c)] += 1
missing, start, min_start, min_len = n, 0, 0, float('inf')
for end in range(m):
if need[ord(s[end])] > 0: missing -= 1
need[ord(s[end])] -= 1
while missing == 0:
if end - start + 1 < min_len:
min_len = end - start + 1
min_start = start
need[ord(s[start])] += 1
if need[ord(s[start])] > 0: missing += 1
start += 1
return "" if min_len == float('inf') else s[min_start:min_start + min_len]
π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated