题目:
给定一个二维网格 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
方法一:
利用单词列表建立前缀树,利用前缀树在字母表上进行搜索。
class Node:
def __init__(self, val=None):
self.val = val
self.next = {}
self.isend = None
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
h = len(board)
if h==0:
return []
w = len(board[0])
if w==0:
return []
n = len(words)
if n==0:
return []
root = Node()
for word in words:
self.build_Trie(root, word)
result = []
used = [[0]*w for i in range(h)]
for i in range(h):
for j in range(w):
if board[i][j] in root.next.keys():
self.findstr(board, root, [i,j], used, [h,w], result)
return result
def findstr(self, board, root, index, used, size, result):
dindexs = [[0,1],[0,-1],[1,0],[-1,0]]
h = size[0]
w = size[1]
x = index[0]
y = index[1]
if board[x][y] not in root.next.keys():
return
if root.next[board[x][y]].isend is not None:
result.append(root.next[board[x][y]].isend)
root.next[board[x][y]].isend=None
used[x][y]=1
for dindex in dindexs:
dx = dindex[0]
dy = dindex[1]
i = x+dx
j = y+dy
if i>=0 and i<h and j>=0 and j<w and used[i][j]==0:
self.findstr(board, root.next[board[x][y]], [i,j], used, size, result)
used[x][y]=0
def build_Trie(self, root, word):
head = root
for s in word:
if s in head.next.keys():
head = head.next[s]
else:
head.next[s] = Node(s)
head = head.next[s]
head.isend = word