LeetCode 0208
About 3 min
0208. Implement Trie (Prefix Tree)
- Thẻ: Thiết kế, Cây tiền tố, Bảng băm, Chuỗi
- Độ khó: Trung bình
Tóm tắt đề bài
Yêu cầu: Triển khai lớp Trie
để tạo cây tiền tố.
Lớp Trie
:
Trie()
Khởi tạo đối tượng cây tiền tố.void insert(String word)
Chèn chuỗiword
vào cây tiền tố.boolean search(String word)
Trả vềTrue
nếu chuỗiword
có trong cây tiền tố (nghĩa là đã chèn trước đó); ngược lại trả vềFalse
.boolean startsWith(String prefix)
Trả vềTrue
nếu một trong các tiền tố của chuỗiword
đã chèn trước đó làprefix
; ngược lại trả vềFalse
.
Giải thích:
- .
word
vàprefix
chỉ chứa các ký tự chữ cái thường.- Số lần gọi
insert
,search
vàstartsWith
không vượt quá tổng cộng lần.
Ví dụ:
- Ví dụ 1:
Input:
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
Output:
[null, null, true, false, true, null, true]
Giải thích:
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // Trả về True
trie.search("app"); // Trả về False
trie.startsWith("app"); // Trả về True
trie.insert("app");
trie.search("app"); // Trả về True
Ý tưởng giải quyết
Ý tưởng 1: Cây tiền tố (Trie)
Cây tiền tố (Trie) là một cây nhiều nhánh, trong đó mỗi nút chứa một mảng con trỏ children
trỏ đến các nút con và một biến boolean isEnd
. children
được sử dụng để lưu trữ các nút con tương ứng với các ký tự hiện tại, thường có độ dài bằng số lượng ký tự khác nhau, hoặc có thể sử dụng bảng băm thay thế cho mảng con trỏ. isEnd
được sử dụng để xác định xem nút hiện tại có phải là kết thúc của một chuỗi hay không.
Dưới đây là các bước cụ thể để chèn và tìm kiếm tiền tố:
Chèn chuỗi:
- Bắt đầu từ nút gốc, chèn chuỗi vào cây tiền tố. Đối với ký tự cần chèn, có hai trường hợp xảy ra:
- Nếu nút tương ứng với ký tự đã tồn tại, di chuyển đến nút con và tiếp tục xử lý ký tự tiếp theo.
- Nếu nút tương ứng với ký tự không tồn tại, tạo một nút mới, lưu trữ nút mới đó trong
children
tại vị trí tương ứng, sau đó di chuyển đến nút con và tiếp tục xử lý ký tự tiếp theo.
- Lặp lại các bước trên cho đến khi xử lý xong ký tự cuối cùng, sau đó đánh dấu nút hiện tại là kết thúc của chuỗi.
Tìm kiếm tiền tố:
- Bắt đầu từ nút gốc, tìm kiếm tiền tố trong cây. Đối với ký tự cần tìm kiếm, có hai trường hợp xảy ra:
- Nếu nút tương ứng với ký tự tồn tại, di chuyển đến nút con và tiếp tục tìm kiếm ký tự tiếp theo.
- Nếu nút tương ứng với ký tự không tồn tại, có nghĩa là cây tiền tố không chứa tiền tố đó, trả về giá trị
False
.
- Lặp lại các bước trên cho đến khi tìm kiếm xong ký tự cuối cùng, nếu nút hiện tại khác
None
và là kết thúc của một chuỗi, thì cây tiền tố chứa tiền tố đó.
Ý tưởng 1: Code
class Node:
def __init__(self):
self.children = dict()
self.isEnd = False
class Trie:
def __init__(self):
self.root = Node()
def insert(self, word: str) -> None:
cur = self.root
for ch in word:
if ch not in cur.children:
cur.children[ch] = Node()
cur = cur.children[ch]
cur.isEnd = True
def search(self, word: str) -> bool:
cur = self.root
for ch in word:
if ch not in cur.children:
return False
cur = cur.children[ch]
return cur is not None and cur.isEnd
def startsWith(self, prefix: str) -> bool:
cur = self.root
for ch in prefix:
if ch not in cur.children:
return False
cur = cur.children[ch]
return cur is not None
Ý tưởng 1: Độ phức tạp
- Độ phức tạp thời gian: Khởi tạo là . Thời gian chèn và tìm kiếm là . Trong đó là độ dài của chuỗi được chèn hoặc tìm kiếm.
- Độ phức tạp không gian: . Trong đó là tổng độ dài của các chuỗi được chèn và là kích thước của bộ ký tự.