Skip to content

Commit 9a12938

Browse files
committed
solve(w09): 76. Minimum Window Substring
1 parent 10b7564 commit 9a12938

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# https://leetcode.com/problems/minimum-window-substring/
2+
3+
class Solution:
4+
def minWindow1(self, s: str, t: str) -> str:
5+
"""
6+
[Complexity]
7+
- TC: O(m * k + n) (k = is_included() = len(set(t)))
8+
- SC: O(k) (res ์ œ์™ธ)
9+
10+
[Approach]
11+
๋‹ค์Œ๊ณผ ๊ฐ™์€ counter๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ, two pointer๋กœ window๋ฅผ ์ด๋™ํ•˜๋ฉฐ min window substring์„ ํŠธ๋ž˜ํ‚นํ•œ๋‹ค.
12+
- ์ƒ์„ฑ ์‹œ) t์˜ ๋ชจ๋“  ๋ฌธ์ž์— ๋Œ€ํ•ด ++
13+
- pointer ์ด๋™ ์‹œ) window์— ํฌํ•จ๋˜๋Š” ๋ฌธ์ž ์ค‘ t์— ์†ํ•˜๋Š” ๋ฌธ์ž์— ๋Œ€ํ•ด --
14+
"""
15+
from collections import Counter
16+
17+
# early stop
18+
m, n = len(s), len(t)
19+
if m < n:
20+
return ""
21+
22+
# t์— ๋Œ€ํ•œ counter ์ƒ์„ฑ
23+
counter = Counter(t)
24+
25+
# t์˜ ๋ชจ๋“  ๋ฌธ์ž๊ฐ€ window์— ํฌํ•จ๋˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ํ•จ์ˆ˜
26+
def is_included():
27+
# counter์˜ ๋ชจ๋“  ๊ฐ’์ด 0 ์ดํ•˜์ด๋ฉด, t์˜ ๋ชจ๋“  ๋ฌธ์ž๊ฐ€ window์— ํฌํ•จ๋˜๋Š” ๊ฒƒ (์ค‘๋ณต ํฌํ•จ)
28+
return all(c <= 0 for c in counter.values())
29+
30+
lo, min_len = 0, 1e6
31+
res = ""
32+
33+
for hi in range(m):
34+
# ํ˜„์žฌ window์— ํฌํ•จ๋œ ๋ฌธ์ž๋ฅผ counter์— ๋ฐ˜์˜
35+
if s[hi] in counter:
36+
counter[s[hi]] -= 1
37+
38+
# t์˜ ๋ชจ๋“  ๋ฌธ์ž๊ฐ€ window์— ํฌํ•จ๋˜์–ด์žˆ๋‹ค๋ฉด(= counter์˜ ๋ชจ๋“  ๊ฐ’์ด <= 0์ด๋ฉด),
39+
# counter ๊ฐ’์ด ์Œ์ˆ˜ ~ 0์ด ๋  ๋•Œ๊นŒ์ง€ lo ์ฆ๊ฐ€์‹œํ‚ค๋ฉด์„œ (min window๋ฅผ ๊ตฌํ•ด์•ผํ•˜๋ฏ€๋กœ) counter ์—…๋ฐ์ดํŠธ
40+
if is_included():
41+
while True:
42+
# window์˜ ์ฒซ ๋ฒˆ์งธ ๋ฌธ์ž๊ฐ€ t์— ์†ํ•˜๋Š” ๋ฌธ์ž๋ผ๋ฉด
43+
if s[lo] in counter:
44+
# counter์—์„œ์˜ ๊ฐ’์ด 0์ด๋ฉด, ๋”์ด์ƒ lo๋ฅผ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ค„์ผ ์ˆ˜ ์—†์Œ
45+
if counter[s[lo]] == 0:
46+
break
47+
# coutner์—์„œ์˜ ๊ฐ’์ด ์Œ์ˆ˜๋ผ๋ฉด, lo๋ฅผ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ค„์ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ counter ๋ฐ˜์˜
48+
else:
49+
counter[s[lo]] += 1
50+
# lo๋ฅผ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํ•œ ์นธ ์ด๋™
51+
lo += 1
52+
53+
# (1) t์˜ ๋ชจ๋“  ๋ฌธ์ž๊ฐ€ window์— ํฌํ•จ๋˜์–ด ์žˆ๊ณ  (2) ํ˜„์žฌ window์˜ length๊ฐ€ min_len ๋ณด๋‹ค ์ž‘๋‹ค๋ฉด
54+
# window substring ์—…๋ฐ์ดํŠธ
55+
if is_included() and (new_len := hi - lo + 1) < min_len:
56+
min_len = new_len
57+
res = s[lo:hi + 1]
58+
59+
return res
60+
61+
def minWindow(self, s: str, t: str) -> str:
62+
"""
63+
[Complexity]
64+
- TC: O(m + n)
65+
- SC: O(k)
66+
67+
[Approach]
68+
1) ์œ„์˜ ํ’€์ด์—์„œ is_included()๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๋ฐ์— O(k)์ด ์†Œ์š”๋˜๋ฏ€๋กœ,
69+
(t์— ์†ํ•˜๋Š” ๋ฌธ์ž ์ค‘, ์•„์ง window์— ๋ชจ๋‘ ํฌํ•จ๋˜์ง€ ์•Š์€ ๋ฌธ์ž ์ข…๋ฅ˜ ๊ฐœ์ˆ˜)๋ฅผ ํŠธ๋ž˜ํ‚นํ•˜๋Š” ๋ณ€์ˆ˜ remains๋ฅผ ์ด์šฉํ•˜์—ฌ ์ตœ์ ํ™” ํ•œ๋‹ค.
70+
์ฆ‰, remains == 0์ด๋ผ๋ฉด is_included()์ธ ๊ฒƒ๊ณผ ๋™์ผํ•˜๋‹ค.
71+
2) ๋ฐ˜๋ณต๋ฌธ ์•ˆ์—์„œ ๋ฌธ์ž์—ด ์Šฌ๋ผ์ด์‹ฑ์œผ๋กœ res๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ๋•Œ ์ถ”๊ฐ€์ ์ธ ๋ณต์žก๋„๊ฐ€ ์†Œ์š”๋œ๋‹ค.
72+
๋”ฐ๋ผ์„œ min window์— ๋Œ€ํ•œ pointer์ธ min_lo, min_hi๋งŒ ํŠธ๋ž˜ํ‚นํ•˜๊ณ , return ๋ฌธ์—์„œ ๋ฌธ์ž์—ด ์Šฌ๋ผ์ด์‹ฑ์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
73+
๋‹จ, min window substring์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ๋นˆ ๋ฌธ์ž์—ด์ด ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, min_lo ~ min_hi - 1 ๋ฒ”์œ„๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•œ๋‹ค.
74+
"""
75+
from collections import Counter
76+
77+
# early stop
78+
m, n = len(s), len(t)
79+
if m < n:
80+
return ""
81+
82+
# t์— ๋Œ€ํ•œ counter ์ƒ์„ฑ
83+
counter = Counter(t)
84+
85+
# counter์˜ ๊ฐ’์„ ๋ชจ๋‘ ํ™•์ธํ•˜๋Š” is_include() ์ตœ์ ํ™”
86+
remains = len(counter) # t์— ์†ํ•˜๋Š” ๋ฌธ์ž ์ค‘, ์•„์ง window์— ๋ชจ๋‘ ํฌํ•จ๋˜์ง€ ์•Š์€ ๋ฌธ์ž ์ข…๋ฅ˜ ๊ฐœ์ˆ˜
87+
lo = min_lo = min_hi = 0
88+
min_len = m + 1
89+
90+
for hi in range(m):
91+
# ํ˜„์žฌ window์— ํฌํ•จ๋œ ๋ฌธ์ž๋ฅผ counter์— ๋ฐ˜์˜
92+
if s[hi] in counter:
93+
counter[s[hi]] -= 1
94+
# ํ˜„์žฌ window์— ํ•ด๋‹น ๋ฌธ์ž๊ฐ€ t์— ์กด์žฌํ•˜๋Š” ๊ฐœ์ˆ˜๋งŒํผ ๋“ค์–ด์™€์žˆ๋‹ค๋ฉด, remains--
95+
if counter[s[hi]] == 0:
96+
remains -= 1
97+
98+
# t์˜ ๋ชจ๋“  ๋ฌธ์ž๊ฐ€ window์— ํฌํ•จ๋˜์–ด์žˆ๋Š” ๋™์•ˆ lo ์ด๋™
99+
while not remains:
100+
# ์ตœ์†Œ ๊ธธ์ด window substring ๊ฐฑ์‹ 
101+
if (new_len := hi - lo + 1) < min_len:
102+
min_len, min_lo, min_hi = new_len, lo, hi + 1
103+
104+
# lo ์ด๋™ ์ „, counter ์—…๋ฐ์ดํŠธ
105+
if s[lo] in counter:
106+
counter[s[lo]] += 1
107+
# counter์˜ ๊ฐ’์ด 0 ์ดˆ๊ณผ๊ฐ€ ๋œ๋‹ค๋ฉด, ๋”์ด์ƒ window์— ํ•ด๋‹น ๋ฌธ์ž๊ฐ€ ๋ชจ๋‘ ๋“ค์–ด์žˆ์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ด๋ฏ€๋กœ remains++
108+
if counter[s[lo]] > 0:
109+
remains += 1
110+
111+
# lo๋ฅผ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ํ•œ ์นธ ์ด๋™
112+
lo += 1
113+
114+
return s[min_lo:min_hi]

0 commit comments

Comments
ย (0)