Skip to content

Commit 2ff5051

Browse files
authored
Merge pull request #441 from haklee/main
[haklee] week 5
2 parents 611de3a + 4344baa commit 2ff5051

File tree

5 files changed

+292
-0
lines changed

5 files changed

+292
-0
lines changed

โ€Ž3sum/haklee.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""TC: O(n^2), SC: O(n^2)
2+
3+
์•„์ด๋””์–ด:
4+
- ํ•ฉ์ด 0(์ฆ‰, ๊ณ ์ •๊ฐ’)์ด ๋˜๋Š” ์„ธ ์ˆ˜๋ฅผ ์ฐพ๋Š” ๊ฒƒ์ด ๋ฌธ์ œ.
5+
- ์„ธ ์ˆ˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๊ณ ์ •๋˜์–ด ์žˆ๋‹ค๋ฉด, ๊ทธ๋ฆฌ๊ณ  ์ˆซ์ž๋“ค์ด ๋“ค์–ด์žˆ๋Š” ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ •๋ ฌ๋˜์–ด ์žˆ๋‹ค๋ฉด ํˆฌ ํฌ์ธํ„ฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅ.
6+
- ํˆฌ ํฌ์ธํ„ฐ ํ…Œํฌ๋‹‰์€ ๊ฒ€์ƒ‰ํ•˜๋ฉด ๋งŽ์ด ๋‚˜์˜ค๋ฏ€๋กœ ์•„์ฃผ ์ž์„ธํ•œ ์„ค๋ช…์€ ์ƒ๋žตํ•˜๊ฒ ๋‹ค.
7+
- ์ด ๋ฌธ์ œ์—์„œ๋Š” ๋ฆฌ์ŠคํŠธ์˜ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’๊ณผ ๊ฐ€์žฅ ํฐ ๊ฐ’์— ํฌ์ธํ„ฐ๋ฅผ ๋‘˜ ๊ฒƒ์ด๋‹ค.
8+
- ๊ทธ๋ฆฌ๊ณ  ์ด ๋‘ ๊ฐ’์˜ ํ•ฉ์ด
9+
- ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ณด๋‹ค ์ž‘์œผ๋ฉด ์ž‘์€ ๊ฐ’์˜ ํฌ์ธํ„ฐ๋ฅผ ํฐ ์ชฝ์œผ๋กœ ์˜ฎ๊ธฐ๊ณ ,
10+
- ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ณด๋‹ค ํฌ๋ฉด ํฐ ๊ฐ’์˜ ํฌ์ธํ„ฐ๋ฅผ ์ž‘์€ ์ชฝ์œผ๋กœ ์˜ฎ๊ธด๋‹ค.
11+
- ์ด ๊ณผ์ •์„ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ์›ํ•˜๋Š” ์Œ์„ ์ฐพ๋Š” ๊ฒƒ์ด ๊ด€๊ฑด.
12+
- ๊ณ ์ •๋œ ์ˆซ์ž๋ฅผ ์ •๋ ฌ๋œ ๋ฆฌ์ŠคํŠธ์˜ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’๋ถ€ํ„ฐ ํฐ ๊ฐ’์œผ๋กœ ํ•˜๋‚˜์”ฉ ์˜ฎ๊ฒจ๊ฐ€๋ฉด ์ค‘๋ณต ์—†์ด ํƒ์ƒ‰์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
13+
- ์ด๋•Œ ํˆฌ ํฌ์ธํ„ฐ๋ฅผ ์“ธ ๊ตฌ๊ฐ„์€ ๊ณ ์ •๋œ ์ˆซ์ž ๋’ค์— ์˜ค๋Š” ์ˆซ์ž๋“ค๋กœ ๋‘”๋‹ค.
14+
- ์ฝ”๋“œ๋ฅผ ๋ณด๋Š” ๊ฒƒ์ด ์ดํ•ด๊ฐ€ ๋” ๋น ๋ฅผ ๊ฒƒ์ด๋‹ค..
15+
16+
SC:
17+
- ์ž์„ธํ•œ ์„ค๋ช…์€ TC ๋ถ„์„์—์„œ ํ™•์ธ ๊ฐ€๋Šฅ.
18+
- ์ข…ํ•ฉํ•˜๋ฉด O(n^2).
19+
20+
TC:
21+
- nums๋ฅผ sortํ•˜๋Š” ๊ณผ์ •์—์„œ O(n * log(n))
22+
- ์ •๋ ฌ๋œ nums๋ฅผ ๋ชจ๋‘ ์ˆœํšŒ.
23+
- ๊ทธ๋ฆฌ๊ณ  ๊ฐ ์ˆœํšŒ๋งˆ๋‹ค n-1, n-2, ..., 2 ํฌ๊ธฐ์˜ ๊ตฌ๊ฐ„์—์„œ ํˆฌ ํฌ์ธํ„ฐ ์‚ฌ์šฉ.
24+
- ํˆฌ ํฌ์ธํ„ฐ๋ฅผ ์‚ฌ์šฉํ• ๋•Œ ๋‹จ์ˆœ ์‚ฌ์น™์—ฐ์‚ฐ ๋ฐ ๋น„๊ต์—ฐ์‚ฐ๋งŒ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ O(1).
25+
- ํˆฌ ํฌ์ธํ„ฐ ์‚ฌ์šฉ์‹œ ๋งค ๊ณ„์‚ฐ๋งˆ๋‹ค ํฌ์ธํ„ฐ ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ๊ฐ€ 1์”ฉ ์ค„์–ด๋“ ๋‹ค(s๊ฐ€ ์˜ฌ๋ผ๊ฐ€๋“  e๊ฐ€ ๋‚ด๋ ค๊ฐ€๋“ ).
26+
- (SC) ๋งค ๊ณ„์‚ฐ๋งˆ๋‹ค ์ตœ๋Œ€ ํ•œ ๋ฒˆ solution์„ ์ถ”๊ฐ€ํ•˜๋Š” ์—ฐ์‚ฐ์„ ํ•œ๋‹ค.
27+
- ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๊ฐ ์ˆœํšŒ๋งˆ๋‹ค C * (n-1), C * (n-2), ..., C * 1์˜ ์‹œ๊ฐ„์ด ๋“ค์–ด๊ฐ.
28+
- (SC) ๋น„์Šทํ•˜๊ฒŒ, ๋งค ์ˆœํšŒ๋งˆ๋‹ค ์œ„์™€ ๊ฐ™์€ ๊ผด๋กœ solution ๊ฐœ์ˆ˜๊ฐ€ ๋”ํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.
29+
- ์ข…ํ•ฉํ•˜๋ฉด O(n^2)
30+
- ์ด O(n^2)
31+
"""
32+
33+
from collections import Counter
34+
35+
36+
class Solution:
37+
def threeSum(self, nums: List[int]) -> List[List[int]]:
38+
# ์ปคํŒ…. ์–ด์ฐจํ”ผ ์„ธ ์Œ์˜ ์ˆซ์ž์— ๋“ฑ์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ™์€ ์ˆซ์ž ๊ฐœ์ˆ˜๊ฐ€ ์ตœ๋Œ€ 3๊ฐœ์ด๋ฏ€๋กœ,
39+
# ์ฒ˜์Œ ์ฃผ์–ด์ง„ nums์— ๊ฐ™์€ ์ˆซ์ž๊ฐ€ ๋„ค ๋ฒˆ ์ด์ƒ ๋“ฑ์žฅํ•˜๋ฉด ์„ธ ๋ฒˆ๋งŒ ๋‚˜์˜ค๋„๋ก ๋ฐ”๊ฟ”์ค€๋‹ค.
40+
# ์ด ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋ฉด ๊ฐ™์€ ์ˆซ์ž๊ฐ€ ๋งŽ์ด ๋ฐ˜๋ณต๋˜๋Š” ์ผ€์ด์Šค์—์„œ ์‹œ๊ฐ„ ๊ฐœ์„ ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.
41+
# Counter ์“ฐ๋Š” ๋ฐ์— O(n), ์ƒˆ๋กœ tmp_nums ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ์— O(n)์˜ ์‹œ๊ฐ„์ด ๋“ค์–ด๊ฐ€๋ฏ€๋กœ
42+
# ์ตœ์ข…์ ์ธ ์‹œ๊ฐ„ ๋ณต์žก๋„์— ์˜ํ–ฅ์„ ์ฃผ์ง€๋Š” ์•Š๋Š”๋‹ค.
43+
tmp_nums = []
44+
for k, v in Counter(nums).items():
45+
tmp_nums += [k] * min(v, 3)
46+
47+
# ์—ฌ๊ธฐ๋ถ€ํ„ฐ๊ฐ€ ์ฃผ๋œ ๊ตฌํ˜„.
48+
sorted_nums = sorted(tmp_nums) # TC: O(n * log(n))
49+
nums_len = len(tmp_nums)
50+
51+
sol = set()
52+
for i in range(nums_len): # TC: O(n)
53+
if i > 0 and sorted_nums[i] == sorted_nums[i - 1]:
54+
# ์ปคํŒ…. ๊ณ ์ • ๊ฐ’์ด ์ด๋ฏธ ํ•œ ๋ฒˆ ์‚ฌ์šฉ๋˜์—ˆ๋˜ ๊ฐ’์ด๋ฉด ์Šคํ‚ตํ•ด๋„ ๊ดœ์ฐฎ๋‹ค.
55+
continue
56+
s, e = i + 1, nums_len - 1
57+
while s < e:
58+
# ์ด while๋ฌธ ์ „์ฒด์—์„œ TC O(n).
59+
v = sorted_nums[s] + sorted_nums[e]
60+
if v == -sorted_nums[i]:
61+
# i < s < e ์ด๋ฏ€๋กœ, ์ด ์ˆœ์„œ๋Œ€๋กœ ์ˆซ์ž๋Š” ์ •๋ ฌ๋œ ์ƒํƒœ๋‹ค.
62+
# ์ฆ‰, ๊ฐ™์€ ๊ฐ’์„ ์‚ฌ์šฉํ•œ ์ˆœ์„œ๋งŒ ๋‹ค๋ฅธ ์Œ์„ ๊ฑฑ์ •ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
63+
sol.add((sorted_nums[i], sorted_nums[s], sorted_nums[e]))
64+
if v < -sorted_nums[i]:
65+
# s, e์˜ ๋‘ ๊ฐ’์„ ๋”ํ•œ ๊ฒƒ์ด ์›ํ•˜๋Š” ๊ฐ’๋ณด๋‹ค ์ž‘์œผ๋ฉด, ์ž‘์€ ์ชฝ์— ์žˆ๋Š” ํฌ์ธํ„ฐ๋ฅผ
66+
# ๋” ํฐ ์ˆซ์ž๊ฐ€ ์žˆ๋Š” ์ชฝ์œผ๋กœ ์˜ฎ๊ธฐ๋ฉด ๋œ๋‹ค.
67+
# ์—ฌ๊ธฐ์„œ๋„ ์ค‘๋ณต ๊ฐ’ ์ปคํŒ…์„ ํ•˜๋ ค๋ฉด ํ•  ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, ์ด ์ปคํŒ…์„ ์•ˆ ํ•˜๋ ค๊ณ 
68+
# ๋งจ ์•ž์—์„œ ๊ฐ™์€ ์ˆซ์ž๋“ค์„ ๋ฏธ๋ฆฌ ์ตœ๋Œ€ํ•œ ์ œ๊ฑฐํ•ด๋‘์—ˆ๋‹ค.
69+
s += 1
70+
else:
71+
# s, e์˜ ๋‘ ๊ฐ’์„ ๋”ํ•œ ๊ฒƒ์ด ์›ํ•˜๋Š” ๊ฐ’๋ณด๋‹ค ํฌ๋ฉด, ํฐ ์ชฝ์— ์žˆ๋Š” ํฌ์ธํ„ฐ๋ฅผ
72+
# ๋” ์ž‘์€ ์ˆซ์ž๊ฐ€ ์žˆ๋Š” ์ชฝ์œผ๋กœ ์˜ฎ๊ธฐ๋ฉด ๋œ๋‹ค.
73+
# ์—ฌ๊ธฐ์„œ๋„ ์ค‘๋ณต ๊ฐ’ ์ปคํŒ…์„ ํ•˜๋ ค๋ฉด ํ•  ์ˆ˜ ์žˆ๊ฒ ์ง€๋งŒ, ์ด ์ปคํŒ…์„ ์•ˆ ํ•˜๋ ค๊ณ 
74+
# ๋งจ ์•ž์—์„œ ๊ฐ™์€ ์ˆซ์ž๋“ค์„ ๋ฏธ๋ฆฌ ์ตœ๋Œ€ํ•œ ์ œ๊ฑฐํ•ด๋‘์—ˆ๋‹ค.
75+
e -= 1
76+
return sol # ํƒ€์ž…ํžŒํŠธ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š์•„๋„ ์ œ์ถœ์€ ๋œ๋‹ค...
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""TC: O(n), SC: O(1)
2+
3+
์•„์ด๋””์–ด:
4+
- ํŠน์ • ์‹œ์ ์—์„œ stock์„ ํŒ”์•˜์„๋•Œ ์ตœ๊ณ  ์ˆ˜์ต์ด ๋‚˜๋ ค๋ฉด ์ด์ „ ๊ฐ€๊ฒฉ ์ค‘ ๊ฐ€์žฅ ๋‚ฎ์€ ๊ฐ€๊ฒฉ์— stock์„ ์‚ฌ์•ผ ํ•œ๋‹ค.
5+
- ๋ชจ๋“  ์‹œ์ ์— ๋Œ€ํ•ด ์œ„์˜ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋ฉด ์ „์ฒด ๊ธฐ๊ฐ„ ์ค‘ ์ตœ๊ณ  ์ˆ˜์ต์„ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค.
6+
- ์ด๋ฅผ ์œ„ํ•ด์„œ ํŠน์ • ์‹œ์  ์ด์ „๊นŒ์ง€์˜ ๊ฐ€๊ฒฉ ์ค‘ ๊ฐ€์žฅ ์‹ผ ๊ฐ€๊ฒฉ์ธ minp๊ฐ’์„ ๊ด€๋ฆฌํ•˜๊ณ ,
7+
- ๊ฐ ์‹œ์ ์˜ ๊ฐ€๊ฒฉ์—์„œ minp๊ฐ’์„ ๋นผ์„œ `ํ˜„์žฌ ์ตœ๊ณ  ์ˆ˜์ต`์„ ๊ตฌํ•œ ๋‹ค์Œ์—,
8+
- `์ „์ฒด ์ตœ๊ณ  ์ˆ˜์ต`์„ max(`ํ˜„์žฌ ์ตœ๊ณ  ์ˆ˜์ต`, `์ „์ฒด ์ตœ๊ณ  ์ˆ˜์ต`)์œผ๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.
9+
10+
SC:
11+
- minp, profit(`์ „์ฒด ์ตœ๊ณ  ์ˆ˜์ต`) ๊ฐ’์„ ๊ด€๋ฆฌํ•œ๋‹ค. O(1).
12+
13+
TC:
14+
- prices์˜ ๊ฐ€๊ฒฉ์„ ์ˆœํšŒํ•˜๋ฉด์„œ ๋”ํ•˜๊ธฐ, min, max ์—ฐ์‚ฐ์„ ํ•œ๋‹ค. O(n).
15+
"""
16+
17+
18+
class Solution:
19+
def maxProfit(self, prices: List[int]) -> int:
20+
minp, profit = prices[0], 0
21+
for p in prices:
22+
profit = max(profit, p - (minp := min(minp, p)))
23+
return profit

โ€Žgroup-anagrams/haklee.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""TC: O(n * l * log(l)), SC: O(n * l)
2+
3+
์ „์ฒด ๋ฌธ์ž์—ด ๊ฐœ์ˆ˜ n๊ฐœ, ๋ฌธ์ž์—ด ์ตœ๋Œ€ ๊ธธ์ด l.
4+
5+
์•„์ด๋””์–ด:
6+
- ๋ชจ๋“  ๋ฌธ์ž์—ด์— ๋Œ€ํ•ด ํ•ด๋‹น ๋ฌธ์ž์—ด์„ ์ด๋ฃจ๋Š” ๋ฌธ์ž ์กฐํ•ฉ์œผ๋กœ ๊ณ ์œ ํ•œ ํ‚ค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ฃผ๋œ ์•„์ด๋””์–ด.
7+
- ๋ฌธ์ž์—ด์„ ํ•ด์ฒดํ•ด์„œ sortํ•œ ๋‹ค์Œ ์ด๋ฅผ ๋ฐ”๋กœ tuple๋กœ ๋งŒ๋“ค์–ด์„œ ํ‚ค๋กœ ์‚ฌ์šฉํ–ˆ๋‹ค.
8+
- list๋ฅผ ๋ฆฌํ„ดํ•˜๋ผ๊ณ  ๋˜์–ด์žˆ๋Š” ๊ฒƒ์„ `dict_values`๋กœ ๋ฆฌํ„ดํ–ˆ์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š์•„์„œ ๊ทธ๋ƒฅ ์ œ์ถœํ–ˆ๋‹ค.
9+
10+
SC:
11+
- dict ๊ด€๋ฆฌ.
12+
- ํ‚ค๊ฐ’ ์ตœ๋Œ€ n๊ฐœ, ๊ฐ๊ฐ ์ตœ๊ณ  ๊ธธ์ด l. O(n * l).
13+
- ์ด ์•„์ดํ…œ n๊ฐœ, ๊ฐ๊ฐ ์ตœ๊ณ  ๊ธธ์ด l. O(n * l).
14+
- ์ข…ํ•ฉํ•˜๋ฉด O(n * l).
15+
16+
TC:
17+
- strs์— ์žˆ๋Š” ๊ฐ ์•„์ดํ…œ์„ sortํ•จ. O(l * log(l))
18+
- ์œ„์˜ ๊ณผ์ •์„ n๋ฒˆ ๋ฐ˜๋ณต.
19+
- ์ข…ํ•ฉํ•˜๋ฉด O(n * l * log(l)).
20+
"""
21+
22+
23+
class Solution:
24+
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
25+
d = {}
26+
for s in strs:
27+
# k๊ฐ’ ๊ณ„์‚ฐ์ด ์˜ค๋ฅธ์ชฝ์—์„œ ๋จผ์ € ์ด๋ฃจ์–ด์ง€๋Š”๊ตฐ์š”?!
28+
d[k] = d.get(k := tuple(sorted(s)), []) + [s]
29+
return d.values()
30+
31+
32+
"""TC: O(n * l * log(l)), SC: O(n * l)
33+
๊ฐ ๋‹จ์–ด๋ฅผ sortํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋‹จ์–ด๋ฅผ ์ด๋ฃจ๊ณ  ์žˆ๋Š” ๋ฌธ์ž๋ฅผ ์นด์šดํ„ฐ๋กœ ์„ธ์–ด์„œ ์ด ์นด์šดํ„ฐ๋ฅผ ํ‚ค๋กœ ์“ฐ๋Š” ๊ฒƒ์ด
34+
์‹œ๊ฐ„๋ณต์žก๋„์— ๋” ์ข‹์„ ์ˆ˜๋„ ์žˆ๋‹ค. Counter๋ฅผ ์จ์„œ ์•ŒํŒŒ๋ฒณ ๊ฐœ์ˆ˜๋ฅผ dict๋กœ ๋งŒ๋“  ๋‹ค์Œ json.dumps๋กœ str
35+
๋กœ ๋งŒ๋“ค์–ด๋ฒ„๋ฆฌ์ž.
36+
37+
์‹ค์ œ ์ด ์†”๋ฃจ์…˜์„ ์ œ์ถœํ•˜๋ฉด ์„ฑ๋Šฅ์ด ๋ณ„๋กœ ์ข‹์ง€ ์•Š์€๋ฐ, l๊ฐ’์ด ์ž‘์•„์„œ ์œ„์˜ ๊ณผ์ •์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ์— ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€
38+
์˜คํžˆ๋ ค ๋” ๋ถ™๊ธฐ ๋•Œ๋ฌธ์„ ์ถ”์ •๋œ๋‹ค.
39+
"""
40+
41+
from collections import Counter
42+
from json import dumps
43+
44+
45+
class Solution:
46+
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
47+
d = {}
48+
for s in strs:
49+
d[k] = d.get(k := dumps(Counter(s), sort_keys=True), []) + [s]
50+
return d.values()
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
๋‹จ์ˆœํ•œ trie ๊ตฌํ˜„์ด๋ฏ€๋กœ ๋ถ„์„์€ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค.
3+
"""
4+
5+
6+
class Trie:
7+
def __init__(self):
8+
self.next: dict[str, Trie] = {}
9+
self.end: bool = False
10+
11+
def insert(self, word: str) -> None:
12+
cur = self
13+
14+
for c in word:
15+
cur.next[c] = cur.next.get(c, Trie())
16+
cur = cur.next[c]
17+
18+
cur.end = True
19+
20+
def search(self, word: str) -> bool:
21+
cur = self
22+
23+
for c in word:
24+
if c not in cur.next:
25+
return False
26+
cur = cur.next[c]
27+
28+
return cur.end
29+
30+
def startsWith(self, prefix: str) -> bool:
31+
cur = self
32+
33+
for c in prefix:
34+
if c not in cur.next:
35+
return False
36+
cur = cur.next[c]
37+
38+
return True

โ€Žword-break/haklee.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""TC: ?, SC: O(w * l + s^2)
2+
3+
์ชผ๊ฐœ๊ณ ์ž ํ•˜๋Š” ๋‹จ์–ด์˜ ๊ธธ์ด s, wordDict์— ๋“ค์–ด๊ฐ€๋Š” ๋‹จ์–ด ๊ฐœ์ˆ˜ w, wordDict์— ๋“ค์–ด๊ฐ€๋Š” ๋‹จ์–ด ์ตœ๋Œ€ ๊ธธ์ด l
4+
5+
์•„์ด๋””์–ด:
6+
- trie๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฌธ์ œ์—์„œ ๋งŒ๋“  ํด๋ž˜์Šค๋ฅผ ์—ฌ๊ธฐ์„œ ํ•œ ๋ฒˆ ์‚ฌ์šฉํ•ด๋ณด์ž.
7+
- ์ฃผ์–ด์ง„ ๋‹จ์–ด๋“ค์„ ์ „๋ถ€ trie์— ์ง‘์–ด๋„ฃ๋Š”๋‹ค.
8+
- ์ชผ๊ฐœ๋ ค๊ณ  ํ•˜๋Š” ๋‹จ์–ด๋ฅผ trie๋ฅผ ํ†ตํ•ด์„œ ๋งค์นญํ•œ๋‹ค. (`Trie` ํด๋ž˜์Šค์˜ `find_prefix_indices` ๋ฉ”์†Œ๋“œ)
9+
- ๋‹จ์–ด๋ฅผ ์•ž์—์„œ๋ถ€ํ„ฐ ํ•œ ๊ธ€์ž์”ฉ ๋งค์นญํ•˜๋ฉด์„œ
10+
- ์ค‘๊ฐ„์— end๊ฐ€ ์žˆ๋Š” ๋…ธ๋“œ๋ฅผ ๋งŒ๋‚˜๋ฉด `prefix_indices`์— ๊ฐ’์„ ์ถ”๊ฐ€ํ•œ๋‹ค. "์ด ๋‹จ์–ด๋Š” ์ด index
11+
์—์„œ ์ชผ๊ฐœ์งˆ ์ˆ˜ ์žˆ์–ด์š”!" ํ•˜๋Š” ์˜๋ฏธ๋ฅผ ๋‹ด์€ index๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.
12+
- ๊ธ€์ž ๋งค์นญ์ด ์‹คํŒจํ•˜๋ฉด ๋งค์นญ ์ข…๋ฃŒ.
13+
- ๋งค์นญ์ด ๋๋‚˜๊ณ  ๋‚˜์„œ `prefix_indices`๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.
14+
- e.g.) wordDict = ["leet", "le", "code"], s = "leetcode"์ผ๋•Œ
15+
- ์ฒซ ๊ธ€์ž l ๋งค์นญ. ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์Œ.
16+
- ๋‹ค์Œ ๊ธ€์ž e ๋งค์นญ. ์ด ๋…ธ๋“œ๋Š” end๊ฐ€ true๋‹ค. "le"์— ๋Œ€์‘๋˜๊ธฐ ๋•Œ๋ฌธ. prefix_indices์— 2 ์ถ”๊ฐ€.
17+
- ๋‹ค์Œ ๊ธ€์ž e ๋งค์นญ. ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์Œ.
18+
- ๋‹ค์Œ ๊ธ€์ž t ๋งค์นญ. ์ด ๋…ธ๋“œ๋Š” "leet"์— ๋Œ€์‘๋˜์–ด end๊ฐ€ true๋‹ค. prefix_indices์— 4 ์ถ”๊ฐ€.
19+
- ๋‹ค์Œ ๊ธ€์ž c ๋งค์นญ. ๋งค์นญ ์‹คํŒจ ํ›„ ์ข…๋ฃŒ.
20+
- prefix_indices = [2, 4]๋ฅผ ๋ฆฌํ„ด.
21+
- ์œ„์˜ ๋งค์นญ ๊ณผ์ •์ด ๋๋‚˜๋ฉด ์ฃผ์–ด์ง„ ๋‹จ์–ด๋ฅผ ์ชผ๊ฐค ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•๋“ค์ด ์ƒ๊ธด๋‹ค.
22+
- ์ชผ๊ฐœ์ง„ ๋‹จ์–ด์—์„œ ๋’ท ๋ถ€๋ถ„์„ ์ทจํ•œ๋‹ค.
23+
- e.g.) wordDict = ["leet", "le", "code"], s = "leetcode", prefix_indices = [2, 4]
24+
- prefix_indices์˜ ๊ฐ ์•„์ดํ…œ์„ ๋Œ๋ฉด์„œ
25+
- s[2:]๋ฅผ ํ†ตํ•ด์„œ "le/etcode" ์ค‘ ๋’ท ๋ถ€๋ถ„ "etcode"๋ฅผ ์ทจํ•  ์ˆ˜ ์žˆ๋‹ค.
26+
- s[4:]๋ฅผ ํ†ตํ•ด์„œ "leet/code" ์ค‘ ๋’ท ๋ถ€๋ถ„ "code"๋ฅผ ์ทจํ•  ์ˆ˜ ์žˆ๋‹ค.
27+
- ๋งŒ์•ฝ ๋’ท ๋ถ€๋ถ„์ด ๋นˆ ๋ฌธ์ž์—ด("")์ด ๋  ๊ฒฝ์šฐ ํƒ์ƒ‰์— ์„ฑ๊ณตํ•œ ๊ฒƒ์ด๋‹ค.
28+
- ์ฝ”๋“œ ์ƒ์—์„œ๋Š” ๋นˆ ๋ฌธ์ž์—ด๋กœ ํƒ์ƒ‰์„ ์‹œ๋„ํ•  ๊ฒฝ์šฐ ํƒ์ƒ‰ ์„ฑ๊ณต์˜ ์˜๋ฏธ๋กœ true ๋ฐ˜ํ™˜.
29+
- ๋งŒ์•ฝ prefix_indices๊ฐ€ ๋นˆ ๋ฆฌ์ŠคํŠธ๋กœ ์˜จ๋‹ค๋ฉด ์ชผ๊ฐค ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๋Š” ๋œป์ด๋ฏ€๋กœ ํƒ์ƒ‰ ์‹คํŒจ๋‹ค.
30+
- ๊ทธ ์™ธ์—๋Š” ์ทจํ•œ ๋’ท ๋ถ€๋ถ„๋“ค์— ๋Œ€ํ•ด ๊ฐ๊ฐ ๋‹ค์‹œ ์ชผ๊ฐœ๋Š” ๊ฒƒ์„ ์‹œ๋„ํ•œ๋‹ค.
31+
- ์œ„์˜ ๊ณผ์ •์—์„œ ์ชผ๊ฐœ๋Š” ๊ฒƒ์„ ์ด๋ฏธ ์‹คํŒจํ•œ ๋‹จ์–ด๋ฅผ fail_list๋ผ๋Š” set์œผ๋กœ ๊ด€๋ฆฌํ•˜์—ฌ ์ค‘๋ณต ์—ฐ์‚ฐ์„ ๋ง‰๋Š”๋‹ค.
32+
- ์ฆ‰, memoization์„ ํ™œ์šฉ.
33+
34+
SC:
35+
- trie ์ƒ์„ฑ. ์ตœ์•…์˜ ๊ฒฝ์šฐ O(w * l)
36+
- fail list์— ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๋‹จ์–ด ๊ธธ์ด
37+
- 1, 2, ..., s
38+
- O(s^2)
39+
- ์ด๊ฑธ ์ „์ฒด ๋‹จ์–ด๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ ๋Œ€์‹  ๋งจ ์•ž ๊ธ€์ž์˜ index๋ฅผ ์ €์žฅํ•˜๋Š” ์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด O(s)๊ฐ€ ๋  ๊ฒƒ์ด๋‹ค.
40+
์—ฌ๊ธฐ์—์„œ๋Š” ๊ตฌํ˜„ ์ƒ๋žต.
41+
- findํ•จ์ˆ˜์˜ ํ˜ธ์ถœ ์Šคํƒ ์ตœ์•…์˜ ๊ฒฝ์šฐ ํ•œ ๊ธ€์ž์”ฉ ์•ž์—์„œ ๋นผ๋ฉด์„œ ํƒ์ƒ‰ ์‹œ๋„, O(s)
42+
- ์ข…ํ•ฉํ•˜๋ฉด O(w * l) + O(s^2) + O(s) = O(w * l + s^2)
43+
44+
TC:
45+
- ???
46+
"""
47+
48+
49+
class Trie:
50+
def __init__(self):
51+
self.next: dict[str, Trie] = {}
52+
self.end: bool = False
53+
54+
def insert(self, word: str) -> None:
55+
cur = self
56+
57+
for c in word:
58+
cur.next[c] = cur.next.get(c, Trie())
59+
cur = cur.next[c]
60+
61+
cur.end = True
62+
63+
def find_prefix_indices(self, word: str) -> list[str]:
64+
prefix_indices = []
65+
ind = 0
66+
cur = self
67+
68+
for c in word:
69+
ind += 1
70+
if c not in cur.next:
71+
break
72+
cur = cur.next[c]
73+
if cur.end:
74+
prefix_indices.append(ind)
75+
76+
return prefix_indices
77+
78+
79+
class Solution:
80+
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
81+
# init
82+
trie = Trie()
83+
for word in wordDict:
84+
trie.insert(word)
85+
86+
fail_list = set()
87+
88+
# recursive find
89+
def find(word: str) -> bool:
90+
# ๋‹จ์–ด์˜ ์•ž์—์„œ ์ชผ๊ฐค ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ์ „๋ถ€ ์ฐพ์•„์„œ ์ชผ๊ฐœ๊ณ 
91+
# ๋’ค์— ๋‚จ์€ ๋‹จ์–ด๋ฅผ ๋‹ค์‹œ ์ชผ๊ฐœ๋Š” ๊ฒƒ์„ ๋ฐ˜๋ณตํ•œ๋‹ค.
92+
if word == "":
93+
return True
94+
95+
if word in fail_list:
96+
return False
97+
98+
cut_indices = trie.find_prefix_indices(word)
99+
result = any([find(word[i:]) for i in cut_indices])
100+
if not result:
101+
fail_list.add(word)
102+
103+
return result
104+
105+
return find(s)

0 commit comments

Comments
ย (0)