找到了之前的Java 版本
转化成python,LC提交后有一个例子超时未通过,但是在PyCharm里运行了,没有问题,答案正确。看了其他人提交的 python solution 都是类似的解法。
high-level 理解:
1. Trie 就是 为了多词搜索的高效DS,词的开始都是 root node,词的结尾 有endWork 做标记,从 root 到 标记的 path,就是一个单词
2. 有了Trie, board 上就是 从每个 cell,每次一个cell 一个 char 的比较。Order 和 Trie level 是一一对应的
3. 题目中一些特别关键的要求:(1) 同一个词不能 回溯搜索 --> 所以要 在 board 上 mark visited,unmark visited; (2) code, coder, coded, 不属于上述情况,而是 "code" 找到后,相邻的cell 有 'r' 或 'd',可以继续搜索; (3) 为了解决同词多次出现的情况,一旦 这个词 被选中后,就把 Trie 把 endWord set to None.
几个要点,也是出bug的地方
1. build trie 时,curr = root 在每一个词开始
2. mark and unmark cells in board
3. trick, 为了去重,在 Trie 中 set endWord as None after the 1st match.
class TrieNode(object):
def __init__(self):
self.endWord = None
self.next = [None] * 26
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
root = self.buildTrie(words)
res: list[str] = []
m = len(board)
n = len(board[0])
for i in range(m):
for j in range(n):
# deepcopy = copy.deepcopy(board)
# print("deep copy of board:")
# for row in deepcopy:
# print(row)
# print("")
self.dfs(i, j, board, root, res)
return res
def dfs(self, i: int, j: int, board, node: TrieNode, res: List[str]):
m = len(board)
n = len(board[0])
if i < 0 or i >= m or j < 0 or j >= n:
return
letter = board[i][j]
# check if the cell visited
if letter == "#":
return
# check if the letter matches any word at the right level
# the order of the letter in the world should be same as the level in the trie.
idx = ord(letter) - ord("a")
if node.next[idx] is None:
return
# Now the letter matches, ready to go to the next letter
# Mark the cell as visited
board[i][j] = "#"
# let's check if there is a endWord marker, in the next node
# For the reason why the letter in the next node, see how the trie is constructed.
curr = node.next[idx]
if curr.endWord is not None:
res.append(curr.endWord)
self.dfs(i + 1, j, board, curr, res)
self.dfs(i - 1, j, board, curr, res)
self.dfs(i, j + 1, board, curr, res)
self.dfs(i, j - 1, board, curr, res)
board[i][j] = letter
return
def buildTrie(self, words):
root = TrieNode()
# This is the bug!!!
curr = root
for word in words:
curr = root
for letter in word:
idx = ord(letter) - ord('a')
if curr.next[idx] is None:
curr.next[idx] = TrieNode()
curr = curr.next[idx]
curr.endWord = word
return root