边工作边刷题:70天一遍leetcode: day 66
Word Search II
要点:
- board作为visited。为什么dfs最后要unset visited?visited的意义是在当前的dfs stack内,对这题也就是当前path。下一层dfs之后,当前path结果已经得到,但是改点还可能在其他的path上,所以要把visited unset。类似于有向图dfs。
- trie: 一个buildtrie function即可。search和dfs是一起的。
- trie和层次:当前node是当前处理字符的前一个点,所以进入dfs才开始处理当前字符(or board[i][j]),否则会出现["a"], dict=["a”]返回[]的错误。
错误点:
- 类似grid渲染,每个点都可能是起点,所以要loop每个点然后dfs
- 简单dedup:当找到一个词以后,将isLeaf设为False。(7/8/16) 优化 1:直接用word or None表示leaf,这样不用在dfs中记录path和最后重构单词。
- 优化2:每层dfs call之前做边界检查,省了function call的cost:从TLE提高到beat 8%
- 优化3:用map记录每个结点的neighbors而不是用[]*26,从8%提高到beat 50.75%
- 优化4:直接把board size m, n pass in,而不是on-the-fly计算,从50.75% => 73.88%
class Solution(object):
class TrieNode:
def __init__(self):
# self.isLeaf = False
# self.neighbors = [None]*26
self.neighbors = {} # use map instead of list*26 from 8% to 50.75%
self.word = None
@staticmethod
def buildDict(words):
root = Solution.TrieNode()
for w in words:
cur = root
#for i in xrange(len(w)):
for c in w:
# c = ord(w[i])-ord('a')
# if not cur.neighbors[c]:
# cur.neighbors[c]=Solution.TrieNode()
cur = cur.neighbors.setdefault(c, Solution.TrieNode())
# cur=cur.neighbors[c]
cur.word = w # optimal 2: root.word is not the TLE cause
return root
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
def dfs(board, i, j, root, solutions, m, n):
# m = len(board)
# n = len(board[0])
# print i,j
c = board[i][j]
if not (c and c in root.neighbors):
return
board[i][j], root = None, root.neighbors[c]
if root.word:
solutions.append(root.word)
root.word = None
# if i>=m or j>=n or i<0 or j<0:
# return
# c = board[i][j]
#print c
#if board[i][j]!='#' and root.neighbors[ord(c)-ord('a')]:
# rn = root.neighbors[ord(c)-ord('a')]
# resw.append(board[i][j])
# board[i][j]='#'
if i+1<m: # optimal 1: check before funciton call beat 8%
dfs(board, i+1, j, root, solutions, m, n)
if i-1>=0:
dfs(board, i-1, j, root, solutions, m, n)
if j+1<n:
dfs(board, i, j+1, root, solutions, m, n)
if j-1>=0:
dfs(board, i, j-1, root, solutions, m, n)
# # resw.pop()
# for x, y in ((0, -1), (-1, 0), (0, 1), (1, 0)):
# ii, jj = i + x, j + y
# if 0 <= ii < m and 0 <= jj < n:
# dfs(board, ii, jj, root, solutions)
board[i][j]=c
root = Solution.buildDict(words)
solutions = []
# resw = []
m = len(board)
n = len(board[0])
for i in xrange(m):
for j in xrange(n):
dfs(board, i, j, root, solutions, m, n)
return solutions