给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例:
输入:
words = ["oath","pea","eat","rain"] and board =
[
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]
输出: ["eat","oath"]
说明:
你可以假设所有输入都由小写字母 a-z 组成。
提示:
你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
题目提示用前缀树,
所以先开一个trie tree,把所有的单词插入进去,
然后扫描二维矩阵,判断每个字符可不可能是已有单词的第一个字母,
如果有可能,则进行DFS+回溯,试着找到完整的一个单词,
如果找到了完整的一个单词,那么就把它插入到答案里。
class Trie(object):
def __init__(self):
"""
Initialize your data structure here.
"""
self.root = {}
def insert(self, word):
"""
Inserts a word into the trie.
:type word: str
:rtype: None
"""
node = self.root
for char in word:
node = node.setdefault(char, {})
node["end"] = True
def search(self, word):
"""
Returns if the word is in the trie.
:type word: str
:rtype: bool
"""
node = self.root
for char in word:
if char not in node:
return False
node = node[char]
return "end" in node
def startsWith(self, prefix):
"""
Returns if there is any word in the trie that starts with the given prefix.
:type prefix: str
:rtype: bool
"""
node = self.root
for char in prefix:
if char not in node:
return False
node = node[char]
return True
class Solution(object):
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
if not board or not board[0]:
return []
m, n = len(board), len(board[0])
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
tree = Trie()
for word in words:
tree.insert(word)
words = set(words)
res = set()
def dfs(x0, y0, node, tmpword):
visited.add((x0, y0))
for k in range(4):
x = x0 + dx[k]
y = y0 + dy[k]
if 0 <= x < m and 0 <= y < n and board[x][y] in node and (x, y) not in visited:
visited.add((x, y))
dfs(x, y, node[board[x][y]], tmpword + board[x][y])
visited.remove((x,y))
if tmpword in words: #找到一个单词了
res.add(tmpword) #用集合避免重复
for i in range(m):
for j in range(n):
if board[i][j] in tree.root:
visited = set((i,j))
dfs(i, j, tree.root[board[i][j]], board[i][j])
return list(res)