题目
Given a 2D board and a list of words from the dictionary, find all words in the board.
Each word must be constructed from letters of sequentially adjacent cell, where “adjacent” cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.
For example,
Given words = [“oath”,”pea”,”eat”,”rain”] and board =
[
[‘o’,’a’,’a’,’n’],
[‘e’,’t’,’a’,’e’],
[‘i’,’h’,’k’,’r’],
[‘i’,’f’,’l’,’v’]
]
Return [“eat”,”oath”].
Note:
You may assume that all inputs are consist of lowercase letters a-z.
题目要求
给定一个二维的字母表,其中包含a-z的元素,可重复,一个单词列表。判断单词列表中有哪些单词在字母表中可以找到,找到的依据是字母与相邻的字母可以组成该单词,相邻指上下左右,且每个位置的字母只能用一次。
解题思路
此题采用了字典树的结构来存储单词表,每从字母表中找到一个单词,从字典树中将该单词删除。采用深度优先搜索的方式来遍历字母表。并用visited数组存储字母表中的元素是否被访问过。
代码
class Solution(object):
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
if len(board) == 0:
return []
row,col = len(board),len(board[0])
visited = [[False for _ in range(col)] for _ in range(row)]
trie = Trie()
for word in words:
trie.insert(word)
dz = zip([0,0,1,-1],[-1,1,0,0])
res = []
def dfs(word,node,x,y):
child = node.childs.get(board[x][y])
if child == None:
return
node = child
visited[x][y] = True
for dx,dy in dz:
nx,ny = x + dx,y + dy
if nx >= 0 and nx < row and ny >= 0 and ny < col and not visited[nx][ny]:
dfs(word + board[nx][ny],node,nx,ny)
visited[x][y] = False
if node.isWord:
res.append(word)
trie.delete(word)
for x in range(row):
for y in range(col):
dfs(board[x][y],trie.root,x,y)
return res
class TrieNode(object):
def __init__(self):
self.childs = {}
self.isWord = False
class Trie(object):
def __init__(self):
self.root = TrieNode()
def insert(self,word):
node = self.root
for letter in word:
child = node.childs.get(letter)
if child == None:
child = TrieNode()
node.childs[letter] = child
node = child
node.isWord = True
def delete(self,word):
node = self.root
queue = []
for letter in word:
queue.append((letter,node))
child = node.childs.get(letter)
if not child:
return False
node = child
if not node.isWord:
return False
if node.childs:
node.isWord = False
else:
for letter,node in reversed(queue):
del node.childs[letter]
if node.childs or node.isWord:
break
return True