Skip to content

Commit 6c15907

Browse files
leetcode 72
1 parent ede1c27 commit 6c15907

1 file changed

Lines changed: 316 additions & 0 deletions

File tree

Leetcode/Leetcode_72.py

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
"""
2+
LeetCode 76. Minimum Window Substring
3+
=====================================
4+
5+
Problem Statement
6+
-----------------
7+
Given two strings `s` and `t`, return the minimum window substring
8+
of `s` such that every character in `t` (including duplicates)
9+
is included in the window.
10+
11+
If no such substring exists, return an empty string "".
12+
13+
Examples
14+
--------
15+
Input:
16+
s = "ADOBECODEBANC"
17+
t = "ABC"
18+
19+
Output:
20+
"BANC"
21+
22+
Input:
23+
s = "a"
24+
t = "a"
25+
26+
Output:
27+
"a"
28+
29+
Input:
30+
s = "a"
31+
t = "aa"
32+
33+
Output:
34+
""
35+
36+
Approach
37+
--------
38+
Sliding Window + Frequency Counter
39+
40+
1. Store character frequencies of string `t` using Counter.
41+
2. Expand the right pointer and decrease the required count.
42+
3. Once all characters are found (count == 0):
43+
- Try shrinking the window from the left.
44+
- Update the minimum window if a smaller valid window is found.
45+
4. Continue until the entire string is processed.
46+
47+
Key Observation
48+
---------------
49+
Counter values represent how many more occurrences of each character
50+
are still required.
51+
52+
Positive Value -> Character still needed.
53+
Zero Value -> Exact requirement satisfied.
54+
Negative Value -> Extra occurrences present in the current window.
55+
56+
Time Complexity
57+
---------------
58+
O(n)
59+
60+
Each character is visited at most twice:
61+
- Once by the right pointer.
62+
- Once by the left pointer.
63+
64+
Space Complexity
65+
----------------
66+
O(m)
67+
68+
where m = number of unique characters in t.
69+
70+
"""
71+
72+
73+
from collections import Counter
74+
75+
76+
class Solution:
77+
def minWindow(self, s: str, t: str) -> str:
78+
79+
# Edge Case
80+
if len(s) < len(t):
81+
return ""
82+
83+
# Frequency map of characters needed
84+
n = Counter(t)
85+
86+
# Left pointer
87+
l = 0
88+
89+
# Total characters still needed
90+
count = len(t)
91+
92+
# Minimum window length
93+
ans = float('inf')
94+
95+
# Starting index of answer
96+
start = 0
97+
98+
# Expand window using right pointer
99+
for i in range(len(s)):
100+
101+
if s[i] in n:
102+
n[s[i]] -= 1
103+
104+
# Required character found
105+
if n[s[i]] >= 0:
106+
count -= 1
107+
108+
# Valid window found
109+
while count == 0:
110+
111+
# Update minimum window
112+
if i - l + 1 < ans:
113+
ans = i - l + 1
114+
start = l
115+
116+
# Remove left character
117+
if s[l] in n:
118+
n[s[l]] += 1
119+
120+
# Window becomes invalid
121+
if n[s[l]] > 0:
122+
count += 1
123+
124+
l += 1
125+
126+
if ans == float('inf'):
127+
return ""
128+
129+
return s[start:start + ans]
130+
131+
132+
# ============================================================
133+
# Dry Run
134+
# ============================================================
135+
136+
"""
137+
Input:
138+
s = "ADOBECODEBANC"
139+
t = "ABC"
140+
141+
Initial:
142+
n = {'A':1, 'B':1, 'C':1}
143+
count = 3
144+
l = 0
145+
146+
------------------------------------------------------------
147+
i = 0 -> 'A'
148+
149+
n['A'] = 0
150+
count = 2
151+
152+
Window = "A"
153+
154+
------------------------------------------------------------
155+
i = 3 -> 'B'
156+
157+
n['B'] = 0
158+
count = 1
159+
160+
Window = "ADOB"
161+
162+
------------------------------------------------------------
163+
i = 5 -> 'C'
164+
165+
n['C'] = 0
166+
count = 0
167+
168+
Window = "ADOBEC"
169+
170+
Valid Window Found
171+
172+
Length = 6
173+
ans = 6
174+
start = 0
175+
176+
Try Shrinking
177+
178+
Remove 'A'
179+
n['A'] = 1
180+
181+
n['A'] > 0
182+
count = 1
183+
184+
Stop Shrinking
185+
186+
------------------------------------------------------------
187+
Continue Expanding
188+
189+
i = 10 -> 'A'
190+
191+
n['A'] = 0
192+
count = 0
193+
194+
Window Valid Again
195+
196+
Try Shrinking
197+
198+
Remove D
199+
Remove O
200+
Remove B
201+
Remove E
202+
203+
Window = "CODEBA"
204+
205+
Remove C
206+
207+
n['C'] = 1
208+
count = 1
209+
210+
Stop
211+
212+
------------------------------------------------------------
213+
i = 12 -> 'C'
214+
215+
n['C'] = 0
216+
count = 0
217+
218+
Window = "BANC"
219+
220+
Length = 4
221+
222+
ans = 4
223+
start = 9
224+
225+
Try Shrinking
226+
227+
Remove B
228+
229+
n['B'] = 1
230+
count = 1
231+
232+
Stop
233+
234+
------------------------------------------------------------
235+
236+
Answer:
237+
s[9:13]
238+
239+
= "BANC"
240+
241+
Output:
242+
"BANC"
243+
"""
244+
245+
# ============================================================
246+
# Example Usage
247+
# ============================================================
248+
249+
if __name__ == "__main__":
250+
solution = Solution()
251+
252+
print(solution.minWindow("ADOBECODEBANC", "ABC"))
253+
print(solution.minWindow("a", "a"))
254+
print(solution.minWindow("a", "aa"))
255+
256+
257+
"""
258+
Interview Explanation
259+
---------------------
260+
261+
Why do we decrement n[s[i]]?
262+
263+
Because the character has entered the current window.
264+
265+
Example:
266+
Need:
267+
A : 1
268+
269+
After finding one A:
270+
A : 0
271+
272+
Requirement satisfied.
273+
274+
------------------------------------------------
275+
276+
Why check n[s[i]] >= 0 ?
277+
278+
Because only required occurrences should reduce count.
279+
280+
Example:
281+
282+
Need:
283+
A : 1
284+
285+
Window:
286+
A A A
287+
288+
Counter values:
289+
290+
0
291+
-1
292+
-2
293+
294+
Only the first A contributes toward satisfying t.
295+
296+
------------------------------------------------
297+
298+
Why increment n[s[l]] while shrinking?
299+
300+
Because that character leaves the window.
301+
302+
If its count becomes positive,
303+
the window no longer contains enough copies of that character.
304+
305+
------------------------------------------------
306+
307+
Why does this work in O(n)?
308+
309+
Each character:
310+
- enters the window once
311+
- leaves the window once
312+
313+
Hence total operations are linear.
314+
315+
O(n)
316+
"""

0 commit comments

Comments
 (0)