Minimum Window Substring in DSA Python - Time & Space Complexity
We want to understand how the time needed to find the smallest substring containing all characters from another string changes as the input grows.
How does the running time increase when the input strings get longer?
Analyze the time complexity of the following code snippet.
from collections import Counter
def min_window(s: str, t: str) -> str:
need = Counter(t)
missing = len(t)
left = start = end = 0
for right, char in enumerate(s):
if need[char] > 0:
missing -= 1
need[char] -= 1
while missing == 0:
if end == 0 or right - left + 1 < end - start:
start, end = left, right + 1
need[s[left]] += 1
if need[s[left]] > 0:
missing += 1
left += 1
return s[start:end]
This code finds the smallest substring in s that contains all characters of t.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The main loop moves the right pointer through string
s, and the inner while loop moves the left pointer to shrink the window. - How many times: Each character in
sis visited at most twice--once when expanding the right pointer and once when moving the left pointer.
As the input string s grows, the number of operations grows roughly in proportion to its length because each character is processed a limited number of times.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 (each character visited twice) |
| 100 | About 200 |
| 1000 | About 2000 |
Pattern observation: The operations grow linearly with input size, doubling roughly when input size doubles.
Time Complexity: O(n + m)
This means the time to find the minimum window grows linearly with the size of both input strings s and t.
[X] Wrong: "The nested while loop makes this algorithm quadratic, so it must be O(n²)."
[OK] Correct: Although there is a nested loop, each character is visited at most twice in total, so the total work is still linear, not quadratic.
Understanding this sliding window approach and its linear time complexity shows you can handle problems that require careful pointer movement and counting, a valuable skill in many coding challenges.
"What if the input string t contains many repeated characters? How would that affect the time complexity?"
Practice
Minimum Window Substring problem?Solution
Step 1: Understand the problem statement
The problem asks to find the smallest part of a string that has all characters from another string.Step 2: Compare options with problem goal
Only Find the smallest substring in a string that contains all characters of another string matches the goal of finding the smallest substring containing all characters of another string.Final Answer:
Find the smallest substring in a string that contains all characters of another string -> Option AQuick Check:
Minimum Window Substring = Find smallest substring with all chars [OK]
- Confusing with longest substring problems
- Thinking about sorting instead of substring search
- Ignoring the requirement to include all characters
t for the Minimum Window Substring problem?Solution
Step 1: Understand dictionary initialization for counting
We want a dictionary with keys as characters fromtand values initialized to the count of each character int.Step 2: Check each option
count = {char: t.count(char) for char in t} correctly counts the occurrences of each character int.Final Answer:
count = {char: t.count(char) for char in t} -> Option DQuick Check:
Use dict comprehension with t.count(char) to initialize counts [OK]
- Setting counts to 0 instead of actual counts
- Swapping keys and values in dict comprehension
- Using invalid dictionary syntax
def min_window(s, t):
from collections import Counter
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]
print(min_window('ADOBECODEBANC', 'ABC'))Solution
Step 1: Understand the sliding window logic
The code finds the smallest substring in 'ADOBECODEBANC' containing all chars 'A', 'B', 'C'.Step 2: Trace the window updates
The smallest such substring is 'BANC' starting at index 9 and ending at 12.Final Answer:
BANC -> Option CQuick Check:
Minimum window substring = BANC [OK]
- Confusing substring boundaries
- Not updating formed count correctly
- Returning empty string incorrectly
def min_window(s, t):
from collections import Counter
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 s[ans[1]:ans[2]+1]Solution
Step 1: Analyze return statement
The code returns substring using ans indices without checking if a valid window was found.Step 2: Fix missing empty string return
If no window found, ans[0] remains infinity, so return empty string to avoid error.Final Answer:
Return empty string if no valid window found -> Option BQuick Check:
Check ans[0] before return to avoid errors [OK]
- Returning substring without validation
- Ignoring empty result cases
- Overcomplicating window_counts initialization
s = 'aabbcc' and t = 'abc', which of the following modifications to the Minimum Window Substring algorithm will correctly find the smallest substring containing all characters of t even if t has duplicate characters like 'aabc'?Solution
Step 1: Understand the need for frequency counts
Whenthas duplicates, we must count how many times each character appears and match exactly.Step 2: Choose the correct approach
Using a frequency counter fortand comparing counts in the window ensures all duplicates are included.Final Answer:
Use a frequency counter fortand compare counts exactly in the window -> Option AQuick Check:
Count duplicates exactly using frequency counters [OK]
- Ignoring duplicate characters in
t - Using sets which lose count information
- Sorting strings which doesn't help substring search
Ready to prove it?
Pass the test and this pattern moves unknown
