字典树+剪枝。这里的剪枝其实就是如果words里面的单词都找到了,那么就不需要再找了。
具体做法就是对于一条路径,我们如果到达了叶子节点就说明这条路径上的所有单词都已经加入答案了
这样在回溯回的时候可以删除这条路径没有分支的节点了
class Trie(object):
def __init__(self):
self.children = {}
self.word = ""
class Solution(object):
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
root = Trie()
for word in words:
node = root
for ch in word:
if ch not in node.children:
node.children[ch] = Trie()
node = node.children[ch]
node.word = word
def dfs(r,c,node):
if board[r][c] not in node.children:
return
ch = board[r][c]
nxt = node.children[ch]
if nxt.word:
ans.append(nxt.word)
nxt.word = ""
if nxt.children:
board[r][c] = "#"
for nr,nc in [(r+1,c),(r-1,c),(r,c+1),(r,c-1)]:
if 0 <= nr < row and 0 <= nc < col:
dfs(nr,nc,nxt)
board[r][c] = ch #四个方向都不行再回溯
if not nxt.children:
node.children.pop(ch)
ans = []
row,col = len(board),len(board[0])
for r in range(row):
for c in range(col):
dfs(r,c,root)
return ans
前缀树加回溯,前缀树的作用是把单词放到树上,这样就不需要对每个word进行查询,遍历字符矩阵每个元素当作开头看是否能匹配就可以了
class Trie(object):
def __init__(self):
self.children = {}
self.word = ""
class Solution(object):
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
root = Trie()
for word in words:
node = root
for ch in word:
if ch not in node.children:
node.children[ch] = Trie()
node = node.children[ch]
node.word = word
def dfs(r,c,node):
if board[r][c] not in node.children:
return
ch = board[r][c]
node = node.children[ch]
if node.word != "":
ans.add(node.word)
board[r][c] = "#"
for nr, nc in [(r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)]:
if 0 <= nr < m and 0 <= nc < n:
dfs(nr, nc, node)
board[r][c] = ch
ans = set()
m,n = len(board),len(board[0])
for r in range(m):
for c in range(n):
dfs(r,c,root)
return list(ans)
暴力,超时。思路对于每个单词都进入字符矩阵搜索一遍
class Solution(object):
def findWords(self,board, words):
sol, res = [], set()
row = len(board)
col = len(board[0])
mark = [[0]*col for _ in range(row)]
board_count = collections.defaultdict(int)
for i in range(row):
for j in range(col):
board_count[board[i][j]] += 1
def backtrack(r, c, begin):
if len(word) == begin:
res.add("".join(sol[:]))
return
if begin > 10:
return
for nr, nc in [(r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)]:
if 0 <= nr < row and 0 <= nc < col and mark[nr][nc] == 0 and board[nr][nc] == word[begin]:
mark[nr][nc] = 1
sol.append(word[begin])
backtrack(nr, nc, begin + 1)
mark[nr][nc] = 0
sol.pop()
def helper(word, board_count):
count = Counter(word)
for char in word:
if count[char] > board_count[char]:
return False
return True
for word in words:
if helper(word, board_count):
for i in range(row):
for j in range(col):
if word[0] == board[i][j]:
mark[i][j] = 1
sol.append(word[0])
backtrack(i,j,1)
mark[i][j] = 0
sol.pop()
return list(res)