dfs 解决(隐式)图搜索问题
132. 单词搜索 II
中文
English
给出一个由小写字母组成的矩阵和一个字典。找出所有同时在字典和矩阵中出现的单词。一个单词可以从矩阵中的任意位置开始,可以向左/右/上/下四个相邻方向移动。一个字母在一个单词中只能被使用一次。且字典中不存在重复单词
样例
样例 1:
输入:["doaf","agai","dcan"],["dog","dad","dgdg","can","again"]
输出:["again","can","dad","dog"]
解释:
d o a f
a g a i
d c a n
矩阵中查找,返回 ["again","can","dad","dog"]。
样例 2:
输入:["a"],["b"]
输出:[]
解释:
a
矩阵中查找,返回 []。
挑战
使用单词查找树来实现你的算法
DIRECTIONS = [(0, -1), (0, 1), (-1, 0), (1, 0)] class Solution: """ @param board: A list of lists of character @param words: A list of string @return: A list of string """ def wordSearchII(self, board, words): if board is None or len(board) == 0: return [] word_set = set(words) prefix_set = set() for word in words: for i in range(len(word)): prefix_set.add(word[:i + 1]) result = set() for i in range(len(board)): for j in range(len(board[0])): c = board[i][j] self.search( board, i, j, board[i][j], word_set, prefix_set, set([(i, j)]), result, ) return list(result) def search(self, board, x, y, word, word_set, prefix_set, visited, result): if word not in prefix_set: return if word in word_set: result.add(word) for delta_x, delta_y in DIRECTIONS: x_ = x + delta_x y_ = y + delta_y if not self.inside(board, x_, y_): continue if (x_, y_) in visited: continue visited.add((x_, y_)) self.search( board, x_, y_, word + board[x_][y_], word_set, prefix_set, visited, result, ) visited.remove((x_, y_)) def inside(self, board, x, y): return 0 <= x < len(board) and 0 <= y < len(board[0])
注意使用prefix hash map来剪枝。
使用trie的解法:
DIRECTIONS = [(0, -1), (0, 1), (-1, 0), (1, 0)] class TrieNode: #定义字典树的节点 def __init__(self): self.children = {} self.is_word = False self.word = None class Trie: def __init__(self): self.root = TrieNode() def add(self, word): #字典树插入单词 node = self.root for c in word: if c not in node.children: node.children[c] = TrieNode() #在此节点申请节点 node = node.children[c] #继续遍历 node.is_word = True node.word = word #存入单词 def find(self, word): node = self.root for c in word: node = node.children.get(c) if node is None: return None return node class Solution: """ @param board: A list of lists of character @param words: A list of string @return: A list of string """ def wordSearchII(self, board, words): if board is None or len(board) == 0: return [] trie = Trie() for word in words: #插入单词 trie.add(word) result = set() for i in range(len(board)): #遍历字母矩阵,将每个字母作为单词首字母开始搜索 for j in range(len(board[0])): c = board[i][j] self.search( board, i, j, trie.root.children.get(c), set([(i, j)]), result, ) return list(result) def search(self, board, x, y, node, visited, result): #在字典树上dfs查找 if node is None: return if node.is_word: result.add(node.word) for delta_x, delta_y in DIRECTIONS: #向四个方向查找 x_ = x + delta_x y_ = y + delta_y if not self.inside(board, x_, y_): continue if (x_, y_) in visited: continue visited.add((x_, y_)) self.search( board, x_, y_, node.children.get(board[x_][y_]), visited, result, ) visited.remove((x_, y_)) def inside(self, board, x, y): return 0 <= x < len(board) and 0 <= y < len(board[0])