Word Search II
Question
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.
Tags
- Graph
- DFS
Thought
We can use DFS search algorithm + Trie here.
- Build the trie for the word list
- Looping through each position in the board and run DFS with it and the Trie.
Code
class Solution(object):
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
def dfs(word, node, location):
row, col = location
node = node.children.get(board[row][col])
if node is None:
return
dz = [(-1, 0), (1, 0), (0, -1), (0, 1)]
visited[row][col] = True
for x, y in dz:
newRow = row + x
newCol = col + y
if 0 <= newRow < len(board) and 0 <= newCol < len(board[0]) and not visited[newRow][newCol]:
dfs(word + board[newRow][newCol], node, (newRow, newCol))
if node.isWord:
result.add(word)
trie.delete(word)
visited[row][col] = False
trie = Trie()
for word in words:
trie.insert(word)
visited = [[False for i in xrange(len(board[0]))] for j in xrange(len(board))]
result = set()
for row in xrange(len(board)):
for col in xrange(len(board[0])):
dfs(board[row][col], trie.root, (row, col))
return sorted(list(result))
class TrieNode():
def __init__(self):
self.children = {}
self.isWord = False
class Trie():
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for ch in word:
if ch not in node.children:
node.children[ch] = TrieNode()
node = node.children[ch]
node.isWord = True
def delete(self, word):
node = self.root
stack = []
for ch in word:
stack.append((ch, node))
node = node.children.get(ch)
if node is None:
return False
if not node.isWord:
return False
if len(node.children):
node.isWord = False
else:
while stack:
ch, node = stack.pop()
del node.children[ch]
if len(node.children) or node.isWord:
break
return True