208. Implement Trie (Prefix Tree)
A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.
Implement the Trie class:
- Trie() Initializes the trie object.
- void insert(String word) Inserts the string word into the trie.
- boolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.
- boolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.
Example 1:
Input
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
Output
[null, null, true, false, true, null, true]
Explanation
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // return True
trie.search("app"); // return False
trie.startsWith("app"); // return True
trie.insert("app");
trie.search("app"); // return True
Constraints:
- 1 <= word.length, prefix.length <= 2000
- word and prefix consist only of lowercase English letters.
- At most 3 * 104 calls in total will be made to insert, search, and startsWith.
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])
부분 숙지! + 연습!!
'LeetCode > 공통' 카테고리의 다른 글
[LeetCode 75] Medium - 236. Lowest Common Ancestor of a Binary Tree (0) | 2024.11.17 |
---|---|
[LeetCode 75] Medium - 11. Container With Most Water ☆ (1) | 2024.11.12 |
[LeetCode 75] Easy - 392. Is Subsequence (0) | 2024.11.12 |
[LeetCode 75] Medium - 452. Minimum Number of Arrows to Burst Balloons (1) | 2024.11.10 |
[LeetCode 75] Easy - 136. Single Number (0) | 2024.11.09 |