Skip to content

Commit 727931f

Browse files
authored
Analyze: Design add and search words data structure
1 parent 3af0cab commit 727931f

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# ํ•ด์„
2+
# 0. TrieNode ํด๋ž˜์Šค ์ •์˜:
3+
# - ๊ฐ TrieNode ์ธ์Šคํ„ด์Šค๋Š” ๋‹ค์Œ์˜ ๋‘ ๊ฐ€์ง€ ์†์„ฑ์„ ๊ฐ€์ง„๋‹ค:
4+
# 1) children: ํ˜„์žฌ ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ๋“ค์„ ์ €์žฅํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ (๋ฌธ์ž -> TrieNode ์ธ์Šคํ„ด์Šค).
5+
# 2) is_end_of_word: ํ˜„์žฌ ๋…ธ๋“œ๊ฐ€ ๋‹จ์–ด์˜ ๋์ธ์ง€ ๋‚˜ํƒ€๋‚ด๋Š” Boolean ๊ฐ’.
6+
7+
# 1. WordDictionary ํด๋ž˜์Šค ์ •์˜:
8+
# - WordDictionary ํด๋ž˜์Šค๋Š” Trie ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ์–ด๋ฅผ ์ €์žฅ(addWord)ํ•˜๊ณ  ํƒ์ƒ‰(search)ํ•œ๋‹ค.
9+
10+
# 1-1. __init__ ํ•จ์ˆ˜:
11+
# - root๋Š” TrieNode ํด๋ž˜์Šค๋กœ ์ƒ์„ฑ๋œ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ง„๋‹ค.
12+
# - Trie ์ž๋ฃŒ๊ตฌ์กฐ์˜ ์‹œ์ž‘์ (๋ฃจํŠธ ๋…ธ๋“œ) ์—ญํ• ์„ ํ•œ๋‹ค.
13+
14+
# 1-2. addWord ํ•จ์ˆ˜:
15+
# 1) ๋ฃจํŠธ ๋…ธ๋“œ(self.root)์—์„œ ์‹œ์ž‘.
16+
# 2) ๋‹จ์–ด์˜ ๊ฐ ๋ฌธ์ž๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ:
17+
# - ํ˜„์žฌ ๋…ธ๋“œ์˜ children์— ๋ฌธ์ž๊ฐ€ ์—†์œผ๋ฉด, ์ƒˆ TrieNode๋ฅผ ์ƒ์„ฑํ•ด ์ถ”๊ฐ€.
18+
# - ํ˜„์žฌ ๋…ธ๋“œ๋ฅผ ํ•ด๋‹น ๋ฌธ์ž์˜ ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™.
19+
# 3) ๋‹จ์–ด์˜ ๋งˆ์ง€๋ง‰ ๋ฌธ์ž๋ฅผ ์ฒ˜๋ฆฌํ•œ ํ›„, ํ•ด๋‹น ๋…ธ๋“œ์˜ is_end_of_word๋ฅผ True๋กœ ์„ค์ •.
20+
21+
22+
# 1-3. search ํ•จ์ˆ˜:
23+
# - ์ฃผ์–ด์ง„ ๋‹จ์–ด๊ฐ€ Trie์— ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ํ•จ์ˆ˜.
24+
# - ์™€์ผ๋“œ์นด๋“œ ๋ฌธ์ž(.)๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
25+
# - ๋‚ด๋ถ€์ ์œผ๋กœ dfs(๊นŠ์ด ์šฐ์„  ํƒ์ƒ‰) ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠธ๋ผ์ด๋ฅผ ํƒ์ƒ‰.
26+
# - dfs(index, node):
27+
# 1) ์ข…๋ฃŒ ์กฐ๊ฑด: index๊ฐ€ ๋‹จ์–ด ๊ธธ์ด์— ๋„๋‹ฌํ•˜๋ฉด, ํ˜„์žฌ ๋…ธ๋“œ์˜ is_end_of_word ๋ฐ˜ํ™˜.
28+
# 2) ํ˜„์žฌ ๋ฌธ์ž๊ฐ€ '.'์ธ ๊ฒฝ์šฐ:
29+
# - ํ˜„์žฌ ๋…ธ๋“œ์˜ ๋ชจ๋“  ์ž์‹ ๋…ธ๋“œ์— ๋Œ€ํ•ด dfs๋ฅผ ํ˜ธ์ถœ.
30+
# - ํ•˜๋‚˜๋ผ๋„ True๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด True ๋ฐ˜ํ™˜.
31+
# 3) ํ˜„์žฌ ๋ฌธ์ž๊ฐ€ ์ผ๋ฐ˜ ๋ฌธ์ž์ธ ๊ฒฝ์šฐ:
32+
# - ์ž์‹ ๋…ธ๋“œ์— ๋ฌธ์ž๊ฐ€ ์—†์œผ๋ฉด False ๋ฐ˜ํ™˜.
33+
# - ์ž์‹ ๋…ธ๋“œ๋กœ ์ด๋™ํ•ด dfs๋ฅผ ์žฌ๊ท€ ํ˜ธ์ถœ.
34+
35+
36+
37+
#Big O
38+
# - N: ์ €์žฅ๋œ ๋ชจ๋“  ๋‹จ์–ด์˜ ์ด ๋ฌธ์ž ์ˆ˜ (Trie์— ์ €์žฅ๋œ ๋ชจ๋“  ๋ฌธ์ž์˜ ๊ฐœ์ˆ˜).
39+
# - C: ์•ŒํŒŒ๋ฒณ์˜ ๊ฐœ์ˆ˜ (์˜์–ด ๊ธฐ์ค€ ์ตœ๋Œ€ 26).
40+
41+
#Time Complexity: O(N)
42+
#- addWordํ•จ์ˆ˜ : N์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ ๋‹จ์–ด ์ถ”๊ฐ€
43+
#- searchWord ํ•จ์ˆ˜:
44+
# - ์ผ๋ฐ˜ ํƒ์ƒ‰: O(n), n์€ ๋‹จ์–ด์˜ ๊ธธ์ด.
45+
# - ์™€์ผ๋“œ์นด๋“œ ํƒ์ƒ‰: ์ตœ์•…์˜ ๊ฒฝ์šฐ O(C^N),
46+
# - C๋Š” ์•ŒํŒŒ๋ฒณ ๊ฐœ์ˆ˜ (์ตœ๋Œ€ 26).
47+
# - N์€ ๋‹จ์–ด์˜ ๊ธธ์ด. ์™€์ผ๋“œ์นด๋“œ ๋ฌธ์ž๊ฐ€ ๋งŽ์„์ˆ˜๋ก ๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ ํƒ์ƒ‰ํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Œ.
48+
49+
# - Space Complexity: O(N ร— C)
50+
#
51+
# - ๊ฐ ๋…ธ๋“œ๋Š”:
52+
# 1) children ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ํ†ตํ•ด ์ž์‹ ๋…ธ๋“œ๋ฅผ ์ €์žฅ (๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ).
53+
# 2) is_end_of_word ๋ณ€์ˆ˜ (Boolean ๊ฐ’, O(1)).
54+
# - Trie์— ์ €์žฅ๋œ ๋‹จ์–ด์˜ ๋ฌธ์ž ์ˆ˜๊ฐ€ ๋งŽ์„์ˆ˜๋ก ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ์ฆ๊ฐ€.
55+
56+
class TrieNode:
57+
def __init__(self):
58+
self.children = {} #์•ŒํŒŒ๋ฒณ a๋ถ€ํ„ฐ z๊นŒ์ง€๋ฅผ ์ž์‹์œผ๋กœ ๊ฐ€์ง, ํฌ๊ธฐ 26์˜ ๋ฐฐ์—ด์ด๋‚˜ ๋”•์…”๋„ˆ๋ฆฌ๋ฅผ ์‚ฌ์šฉ.
59+
self.is_end_of_word = False #์–ด๋–ค ๋‹จ์–ด์˜ ๋์ธ์ง€ ๋‚˜ํƒ€๋‚ด๋Š” Boolean ๊ฐ’
60+
#์˜ˆ๋ฅผ ๋“ค์–ด, "note"์ด๋ผ๋Š” ๋‹จ์–ด์˜ 'e'์— ํ•ด๋‹นํ•˜๋Š” ๋…ธ๋“œ์˜ is_end_of_word๊ฐ€ True, 'n'
61+
62+
class WordDictionary:
63+
def __init__(self):
64+
self.root = TrieNode() # WD๋กœ ์ƒ์„ฑ๋œ ์ธ์Šคํ„ด์Šค.root = TrieNode ์ธ์Šคํ„ด์Šค
65+
66+
def addWord(self, word: str) -> None:
67+
node = self.root #node์— self.root๋ฅผ ๋ถ€์—ฌ
68+
for char in word: # ๋งค๊ฐœ๋ณ€์ˆ˜ word๋ฅผ ํ•˜๋‚˜์”ฉ ์ˆœํšŒํ•˜๋ฉฐ char์— ์ €์žฅ (์˜ˆ: word="note" -> char="n", "o", "t", "e")
69+
if char not in node.children: # ๋งŒ์•ฝ char๊ฐ€ ํ˜„์žฌ ๋…ธ๋“œ์˜ ์ž์‹ ๋…ธ๋“œ ๋ชฉ๋ก์— ์—†๋‹ค๋ฉด
70+
node.children[char] = TrieNode()
71+
#node.children[char]์„ TrideNode ์ธ์Šคํ„ด์Šค๋กœ ์ƒ์„ฑ
72+
# self.root.children = {
73+
# "n": TrieNode() # "n" ํ‚ค๊ฐ€ ์ถ”๊ฐ€๋˜๊ณ , ๊ฐ’์œผ๋กœ ์ƒˆ๋กœ์šด TrieNode ์ธ์Šคํ„ด์Šค๊ฐ€ ๋“ค์–ด๊ฐ
74+
# }
75+
76+
#Example1:
77+
#root
78+
#โ””โ”€โ”€ "n" (children={}, is_end_of_word=False)
79+
80+
#Example2:
81+
#โ””โ”€โ”€ "n" (children={}, is_end_of_word=False)
82+
# โ””โ”€โ”€ "o" (children={}, is_end_of_word=False)
83+
node = node.children[char] #node๋ฅผ ํ˜„ node์˜ children[char]๋กœ ์ด๋™
84+
#Example1:
85+
# node = node.children["n"]
86+
87+
#Example2:
88+
# node = node.children["o"]
89+
node.is_end_of_word = True
90+
#After for loop, ๋ ๋…ธ๋“œ์˜ is_end_of_word๋ฅผ True๋กœ ์ „ํ™˜
91+
92+
#Example 4:
93+
#root
94+
#โ””โ”€โ”€ "n"
95+
#โ””โ”€โ”€ "o"
96+
#โ””โ”€โ”€ "t"
97+
#โ””โ”€โ”€ "e" (children={}, is_end_of_word=True)
98+
99+
def search(self, word: str) -> bool:
100+
def dfs(index, node): # DFS ํ•จ์ˆ˜ ์ •์˜
101+
# 1) ์ข…๋ฃŒ ์กฐ๊ฑด: ๋ชจ๋“  ๋ฌธ์ž๋ฅผ ํƒ์ƒ‰ํ•œ ๊ฒฝ์šฐ
102+
if index == len(word):
103+
return node.is_end_of_word # ๋‹จ์–ด ๋ ์—ฌ๋ถ€ ๋ฐ˜ํ™˜
104+
# 2) ํ˜„์žฌ ๋ฌธ์ž ์ฒ˜๋ฆฌ
105+
char = word[index]
106+
if char == '.': # 2-1) ์™€์ผ๋“œ์นด๋“œ์ธ ๊ฒฝ์šฐ
107+
for child in node.children.values(): # ๋ชจ๋“  ์ž์‹ ๋…ธ๋“œ ํƒ์ƒ‰
108+
if dfs(index + 1, child): #dfs๋ฅผ ์žฌ๊ท€ํ˜ธ์ถœ ํ•˜์—ฌ ๋‹ค์Œ ๋…ธ๋“œ๋กœ ํƒ์ƒ‰ ์žฌ๊ฐœ
109+
return True #์žฌ๊ท€ ์ดํ›„์— ์žˆ์œผ๋ฉด True
110+
return False #์—†์œผ๋ฉด False
111+
else: # 2-2) ์ผ๋ฐ˜ ๋ฌธ์ž ์ฒ˜๋ฆฌ
112+
if char not in node.children: # ํ˜„์žฌ ๋ฌธ์ž๊ฐ€ ์ž์‹ ๋…ธ๋“œ์— ์—†๋Š” ๊ฒฝ์šฐ False
113+
return False
114+
return dfs(index + 1, node.children[char]) # ๋‹ค์Œ ๋…ธ๋“œ๋กœ ์ด๋™ํ•˜์—ฌ ํƒ์ƒ‰
115+
116+
return dfs(0, self.root)
117+
#1. def dfs๋ฅผ self.root ์œ„์น˜์—์„œ ์ฒซ ํ˜ธ์ถœ.
118+
119+
120+
121+

0 commit comments

Comments
ย (0)