第八章 古墓探险:Trie树寻宝
上古剑仙墓穴开启,墓门机关浮现一行古篆:“唯有通晓前缀之道,方能得见真传”。林玄发现墓室墙壁上刻满各种剑诀前缀。
字典树奥秘
class TrieNode:
def __init__(self):
self.children = {} # 子节点字典
self.is_end = False # 标记是否为单词结尾
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
node.is_end = True
def search(self, word):
node = self.root
for char in word:
if char not in node.children:
return False
node = node.children[char]
return node.is_end
def startsWith(self, prefix):
node = self.root
for char in prefix:
if char not in node.children:
return False
node = node.children[char]
return True
【核心特性】
- 前缀共享节省空间
- 查找时间复杂度O(L),L为单词长度
- 适合自动补全场景
墓室挑战
- 破解剑诀密码(单词搜索II):
def find_words(board, words):
def dfs(node, i, j, path):
if node.is_end:
res.add(path)
tmp = board[i][j]
board[i][j] = '#'
for x, y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:
if 0<=x<m and 0<=y<n and board[x][y] in node.children:
dfs(node.children[board[x][y]], x, y, path+board[x][y])
board[i][j] = tmp
trie = Trie()
for word in words:
trie.insert(word)
res = set()
m, n = len(board), len(board[0])
for i in range(m):
for j in range(n):
if board[i][j] in trie.root.children:
dfs(trie.root.children[board[i][j]], i, j, board[i][j])
return list(res)
- 寻找最长剑诀前缀:
def longest_common_prefix(words):
if not words:
return ""
trie = Trie()
for word in words:
trie.insert(word)
prefix = ""
node = trie.root
while len(node.children) == 1 and not node.is_end:
char = next(iter(node.children))
prefix += char
node = node.children[char]
return prefix
- 剑诀自动补全系统:
def autocomplete(prefix, trie):
node = trie.root
for char in prefix:
if char not in node.children:
return []
node = node.children[char]
res = []
stack = [(node, prefix)]
while stack:
curr_node, curr_prefix = stack.pop()
if curr_node.is_end:
res.append(curr_prefix)
for char, child in curr_node.children.items():
stack.append((child, curr_prefix + char))
return res