208. Implement Trie (Prefix Tree)
https://youtu.be/oobqoCJlHA0?si=rB7vqpOg4d0DiFd1
https://youtu.be/j7Zkw5XWe_Q?si=-yC7nuoxBULmLBuD
이 문제는 Trie(트라이) 자료 구조를 구현하는 것입니다. Trie는 문자열을 효율적으로 저장하고 검색하기 위해 사용되는 트리 형태의 자료 구조입니다. 이 자료 구조는 주로 자동완성, 단어 검색, 접두사 검색과 같은 작업에서 사용됩니다.


Code
# TrieNode 클래스: Trie의 각 노드를 정의
class TrieNode:
def __init__(self):
self.children = {} # 자식 노드를 저장할 해시맵. 키는 문자, 값은 TrieNode 객체
self.endofWord = False # 현재 노드가 단어의 끝인지 여부를 저장
# 예: self.children["a"] = TrieNode()
# Trie 클래스: Trie 자료 구조를 정의
class Trie:
def __init__(self):
self.root = TrieNode() # Trie의 루트 노드를 초기화
# insert 메서드: 주어진 단어를 Trie에 삽입
def insert(self, word: str) -> None:
cur = self.root # 현재 노드를 루트로 초기화
for c in word: # 단어의 각 문자에 대해 반복
if c not in cur.children: # 현재 노드에 문자가 없으면
cur.children[c] = TrieNode() # 해당 문자를 가진 새로운 TrieNode를 추가
cur = cur.children[c] # 다음 노드로 이동
cur.endofWord = True # 단어의 끝을 표시
# search 메서드: 주어진 단어가 Trie에 존재하는지 확인
def search(self, word: str) -> bool:
cur = self.root # 현재 노드를 루트로 초기화
for c in word: # 단어의 각 문자에 대해 반복
if c not in cur.children: # 현재 노드에 문자가 없으면
return False # 단어가 존재하지 않음
cur = cur.children[c] # 다음 노드로 이동
return cur.endofWord # 마지막 노드가 단어의 끝인지 확인
# startsWith 메서드: 주어진 접두사가 Trie에 존재하는지 확인
def startsWith(self, prefix: str) -> bool:
cur = self.root # 현재 노드를 루트로 초기화
for c in prefix: # 접두사의 각 문자에 대해 반복
if c not in cur.children: # 현재 노드에 문자가 없으면
return False # 접두사가 존재하지 않음
cur = cur.children[c] # 다음 노드로 이동
return True # 접두사가 존재하면 True 반환
# Trie 객체 생성 및 메서드 호출 예제
# Your Trie object will be instantiated and called as such:
# obj = Trie() # Trie 객체 생성
# obj.insert(word) # 단어를 Trie에 삽입
# param_2 = obj.search(word) # 단어가 존재하는지 확인
# param_3 = obj.startsWith(prefix) # 접두사가 존재하는지 확인

예제와 시각적 설명



이해를 돕는 비유
Trie를 사용해 단어를 삽입하는 과정은 계단을 하나씩 추가하며 건물을 짓는 것과 같습니다.
- 문자 하나는 계단의 한 층.
- 이전 층이 없으면 새 계단을 만들고 올라가야 합니다.
- 마지막 층에서는 "완성"을 표시 (endofWord = True).

# TrieNode 정의
class TrieNode:
def __init__(self):
# 해시맵, {문자: TrieNode 객체}
self.children_node = {}
# 현재 노드가 단어의 끝인지 여부를 저장
self.prefix_end = False
# 예: self.children_node["a"] = TrieNode()
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word: str) -> None:
cur = self.root # 현재 노드를 루트로 초기화
for c in word:
# 없으면 추가
if c not in cur.children_node:
cur.children_node[c] = TrieNode()
cur = cur.children_node[c] # 다음 노드로 이동
"""
insert: 마지막 char의 prefix_end 에 True 세팅
"""
cur.prefix_end = True # 단어 끝 flag 추가
def search(self, word: str) -> bool:
cur = self.root
for c in word:
# 하나라도 다른게 있으면, false 반환
if c not in cur.children_node:
return False
cur = cur.children_node[c] # 다음 노드로 이동
"""
# search:
insert 단어가 아니면(prefix_end 가 False 이면)
False 반환,
insert 단어이면(prefix_end 가 True 이면)
True 반환
즉, prefix_end 를 반환 하면 됨
"""
return cur.prefix_end
def startsWith(self, prefix: str) -> bool:
cur = self.root
for c in prefix:
# 하나라도 다른게 있으면, false 반환
if c not in cur.children_node:
return False
cur = cur.children_node[c] # 다음 노드로 이동
"""
# startsWith:
prefix_end 가 True 가 아니어도,
여기까지 False 를 반환안했으면,
검색이 됬다는 의미이미, prefix 임
True 반환
"""
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
TrieNode class 정의 와
Trie class 의
- init(),
- insert() 에서
- cur = self.root,
- 다음노드로 이동 (cur = cur.children_node[c])
부분 숙지! + 연습!!
최종 코드
class TrieNode:
def __init__(self):
self.children = {}
self.wordFinish = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word: str) -> None:
cur = self.root
for w in word:
if w not in cur.children:
cur.children[w] = TrieNode()
cur = cur.children[w]
cur.wordFinish = True
def search(self, word: str) -> bool:
cur = self.root
for w in word:
if w not in cur.children:
return False
cur = cur.children[w]
# 검색하는 word 가 prefix 가 아니고, 추가되어있는 word 이면
# cur.wordFinish 가 True 일테고,
# 아니면, False 일테니,
# 무조건 return True 가 아니라.
# 현재 노드가 word의 끝인지 아닌지 확인해주는 wordFinish를 return 하는 것이 맞음
# return True
return cur.wordFinish
def startsWith(self, prefix: str) -> bool:
cur = self.root
for w in prefix:
if w not in cur.children:
return False
cur = cur.children[w]
return True
# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)
'LeetCode > NeetCode' 카테고리의 다른 글
| [LinkedLists: Fast and Slow Pointers] 2130. Maximum Twin Sum of a Linked List ★★★ (1) | 2024.11.15 |
|---|---|
| [Prefix Sums] 238. Product of Array Except Self ☆ (1) | 2024.11.11 |
| Bit: 338. Counting Bits ★★★ (3) | 2024.11.09 |
| [DP: LCS 최장공통수열 Longest Common Subsequence]: 1143. Longest Common Subsequence (1) | 2024.11.08 |
| DP2D: 62. Unique Paths (0) | 2024.11.08 |