134/300
- 单词搜索 II
给定一个二维网格 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
大概形态就是这种 root->{o:{a:{t:{h:{}.True}}}}
从哪个搜就mask哪个,省的有重复的被选上
从此点的上下左右搜,如果词典里刚好有,那么词典翻页,譬如:
搜到’a’, 词典里是{a:{b:{…}}}, “a"的下面正好是"b”,那么词典就翻页到{b:{…}}
board =
[
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]
root->{o:{a:{t:{h:{}.True}}}},{p:{...}},{e:{...}},...
board[0][0] “o” #词典里有
mask [['#', 'a', 'a', 'n'],
['e', 't', 'a', 'e'],#词典翻页到{a:{t:{h:{}.True}}}
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
mask [['#', '#', 'a', 'n'],#右侧词典里有
['e', 't', 'a', 'e'],#词典翻页到{t:{h:{}.True}}
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
mask [['#', '#', 'a', 'n'], #下侧字典里有
['e', '#', 'a', 'e'],#词典翻页到{h:{}.True}
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
mask [['#', '#', 'a', 'n'],
['e', '#', 'a', 'e'],#下侧字典里有
['i', '#', 'k', 'r'],#词典翻页到{{}.True} , 添加路径“oath”
['i', 'f', 'l', 'v']]
恢复找过的路径
recover [['#', '#', 'a', 'n'],
['e', '#', 'a', 'e'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
recover [['#', '#', 'a', 'n'],
['e', 't', 'a', 'e'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
recover [['#', 'a', 'a', 'n'],
['e', 't', 'a', 'e'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
['e', 't', 'a', 'e'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
board[0][1] #词典里无
board[0][2] #词典里无
board[0][3] #词典里无
board[1][0] "e" #词典里有
mask [['o', 'a', 'a', 'n'],
['#', 't', 'a', 'e'], #上下右词典里均无,左侧超界
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
['e', 't', 'a', 'e'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
board[1][1]#词典里无
board[1][2]#词典里无
board[1][3] #以下同理
mask [['o', 'a', 'a', 'n'],
['e', 't', 'a', '#'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
mask [['o', 'a', 'a', 'n'],
['e', 't', '#', '#'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
mask [['o', 'a', 'a', 'n'],
['e', '#', '#', '#'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
['e', 't', '#', '#'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
['e', 't', 'a', '#'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
['e', 't', 'a', 'e'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
board[2][0]
board[2][1]
board[2][2]
board[2][3]
mask [['o', 'a', 'a', 'n'],
['e', 't', 'a', 'e'],
['i', 'h', 'k', '#'],
['i', 'f', 'l', 'v']]
recover [['o', 'a', 'a', 'n'],
['e', 't', 'a', 'e'],
['i', 'h', 'k', 'r'],
['i', 'f', 'l', 'v']]
board[3][0]
board[3][1]
board[3][2]
board[3][3]
变成代码:
class Node:
def __init__(self):
self.next = collections.defaultdict(Node)
self.ends = False
class TrieTree:
def __init__(self):
self.root = Node()
def insert(self, word):
node = self.root
for w in word:
node = node.next[w]
node.ends = True
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
res = []
t = TrieTree()
for word in words:
t.insert(word)
node = t.root
def dfs(node, i, j, path):
if node.ends:
res.append(path)
node.ends = False
if i<0 or j<0 or i>=len(board) or j>=len(board[0]): return
tmp = board[i][j]
node = node.next.get(tmp)
if not node: return
board[i][j] = '#'
for dx, dy in [(0,1),(0,-1),(1,0),(-1,0)]:
dfs(node, i+dx, j+dy, path+tmp)
board[i][j] = tmp
for i in range(len(board)):
for j in range(len(board[0])):
dfs(node, i, j, '')
return res