from typing import List, Dict, Optional, Set
class TrieNode:
"""Trie 树节点类"""
def __init__(self):
# 子节点字典:键是字符,值是对应的 TrieNode 子节点
self.children: Dict[str, TrieNode] = {}
# 存储到达此节点的完整单词(如果它是某个单词的结尾)
# 初始化为 None,表示不是单词结尾
self.word: Optional[str] = None
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
"""
在二维网格中查找单词列表中的所有单词。
"""
if not board or not board[0] or not words:
return []
# 1. 构建 Trie 树
root = TrieNode()
for word in words:
node = root
for char in word:
if char not in node.children:
node.children[char] = TrieNode()
node = node.children[char]
# 在单词结尾的节点存储单词本身
node.word = word
rows, cols = len(board), len(board[0])
# 使用集合存储结果以自动去重
result_set: Set[str] = set()
# 方向数组,方便遍历邻居
directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] # 右, 左, 下, 上
# 定义 DFS 辅助函数
def dfs(r: int, c: int, current_node: TrieNode):
# a. 越界或已访问检查
if not (0 <= r < rows and 0 <= c < cols) or board[r][c] == '#':
return
# b. Trie 剪枝检查
char = board[r][c]
if char not in current_node.children:
return
# --- 状态更新与前进 ---
# 移动到 Trie 的下一个节点
next_node = current_node.children[char]
# 临时标记当前单元格为已访问
original_char = board[r][c] # 保存原始字符
board[r][c] = '#' # 将当前单元格标记为“已在当前路径中访问过”
# c. 检查是否找到单词
if next_node.word is not None: #对于那些不是任何单词结尾的中间节点,它们的 word 属性保持初始值 None。
# 找到了一个单词,添加到结果集
result_set.add(next_node.word)
# 将其从 Trie 中移除(或标记),避免重复查找和作为后续剪枝
next_node.word = None
# 可选优化: 如果 next_node 也没有子节点了,可以考虑从父节点移除它来进一步剪枝
# (这里为了简化,暂时不加这个优化)
# d. 递归探索四个方向的邻居
for dr, dc in directions:
nr, nc = r + dr, c + dc
dfs(nr, nc, next_node)
# e. 回溯:恢复单元格状态
board[r][c] = original_char #目的: 恢复状态,撤销在本层递归开始时所做的“标记访问”(board[r][c] = '#') 衔接: 它确保当 DFS 回溯到上一层(即调用 dfs(r, c, ...) 的那个地方)时,网格 board 的状态与进入 dfs(r, c, ...) 之前的状态是一致的(至少对于 (r, c) 这个单元格是这样) 如3中的 dfs(r, c, root)
# 3. 遍历网格,从每个单元格启动 DFS
for r in range(rows):
for c in range(cols):
# 从根节点开始 DFS
dfs(r, c, root)
# 4. 返回结果
return list(result_set)
# 示例用法:
# solution = Solution()
# board1 = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]]
# words1 = ["oath","pea","eat","rain"]
# print(solution.findWords(board1, words1)) # 输出: ['eat', 'oath']
# board2 = [["a","b"],["c","d"]]
# words2 = ["abcb"]
# print(solution.findWords(board2, words2)) # 输出: []