单词搜索 II
给定一个二维网格 board 和一个字典中的单词列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例:
输入:
words = [“oath”,“pea”,“eat”,“rain”] and board =
[
[‘o’,‘a’,‘a’,‘n’],
[‘e’,‘t’,‘a’,‘e’],
[‘i’,‘h’,‘k’,‘r’],
[‘i’,‘f’,‘l’,‘v’]
]
输出: [“eat”,“oath”]
说明:
你可以假设所有输入都由小写字母 a-z 组成。
提示:
你需要优化回溯算法以通过更大数据量的测试。你能否早点停止回溯?
如果当前单词不存在于所有单词的前缀中,则可以立即停止回溯。什么样的数据结构可以有效地执行这样的操作?散列表是否可行?为什么? 前缀树如何?如果你想学习如何实现一个基本的前缀树,请先查看这个问题: 实现Trie(前缀树)。
1、首先想到的是使用dfs,对每一个输入的单词,采用dfs搜索在board中是否可以获得相应的排序,由于题干中提到用前缀树,因此先把words列表从长到短排序,在判断好每一个单词后,将单词加入前缀树,后续每一个单词首先判断是否是某一个前缀,如果不是再dfs,节省时间。代码如代码一所示,但是!!!在第34个例子中卡住了,时间超时。
2、于是借鉴了网上的思路,将单词一开始全部输入到一个前缀树中,之后任然使用dfs的方法,此时dfs不是判断board当前字符是否在某个单词中,而是判断是否在当前树节点中有子节点。按照该思路,编写了代码二,但是!!!!!在第35个例子中卡住了,超时!但是这就是网上的思路,后来又思考可以在每次搜索到一个单词后在前缀树中删除单词,这样保证不被多次搜索,任然不行。最后使用了别人的代码,然后在答案中找到了代码三,又简洁明了又快速。
!!想要答案的直接代码三
class Solution:
def isPalindrome(self, s):
"""
:type s: str
:rtype: bool
"""
alphanumeric = re.sub("[^A-Za-z0-9]+", "", s).lower()
#正则匹配
print(alphanumeric)
return alphanumeric == alphanumeric[::-1]
class Solution:
def isPalindrome(self, s: 'str') -> 'bool':
s = [c for c in s if c .isalpha() or c.isdigit()]
if len(s) <= 1:
return True
i, j = 0, len(s) - 1
while i < j:
if s[i].lower() != s[j].lower():
return False
i, j = i + 1, j - 1
return True
import copy
class Trie:
def __init__(self):
"""
Initialize your data structure here.
"""
self.root = {}
def insert(self, word):
"""
Inserts a word into the trie.
:type word: str
:rtype: void
"""
node = self.root
for c in word:
if c not in node:
node[c] = {}
node = node[c]
node['flag'] = True
def search(self, word):
"""
Returns if the word is in the trie.
:type word: str
:rtype: bool
"""
node = self.root
for c in word:
if not c in node:
return False
node = node[c]
# Doesn't end here
if 'flag' not in node:
return False
return True
def startsWith(self, prefix):
"""
Returns if there is any word in the trie that starts with the given prefix.
:type prefix: str
:rtype: bool
"""
node = self.root
for c in prefix:
if not c in node:
return False
node = node[c]
return True
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
ans =[]
xlen = len(board[0])
ylen = len(board)
ptree = Trie()
def dfs(word,i,j,aflag):
bflag = copy.deepcopy(aflag)
#print(word,i,j,ans,bflag)
if bflag[i][j]==1 or word[0]!=board[i][j]:
return False
else:
bflag[i][j]=1
if len(word)==1:
return True
if i>0:
if dfs(word[1:],i-1,j,bflag):
return True
if j<xlen-1:
if dfs(word[1:],i,j+1,bflag):
return True
if j>0:
if dfs(word[1:],i,j-1,bflag):
return True
if i<ylen-1:
if dfs(word[1:],i+1,j,bflag):
return True
return False
words.sort(key=lambda x:len(x))
for word in words:
# print(ans,word,words)
flag = 0
if ptree.startsWith(word) :
if ptree.search(word):
pass
else:
ans.append(word)
else:
f = word[0]
bflag = []
for i in range(0, ylen):
tmp = []
for j in range(0, xlen):
tmp.append([0])
bflag.append(tmp)
for i in range(len(board)):
if flag == 1:
break
for j in range(len(board[0])):
print(i,j)
if dfs(word,i,j,bflag):
ptree.insert(word)
ans.append(word)
flag = 1
break
return ans
import copy
class Trie:
def __init__(self):
"""
Initialize your data structure here.
"""
self.root = {}
def insert(self, word):
"""
Inserts a word into the trie.
:type word: str
:rtype: void
"""
node = self.root
for c in word:
if c not in node:
node[c] = {}
node = node[c]
node['flag'] = True
class Solution:
def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
ans =[]
xlen = len(board[0])
ylen = len(board)
ptree = Trie()
for word in words:
ptree.insert(word)
def dfs(c,i,j,aflag,word):
bflag = copy.deepcopy(aflag)
#print(word,i,j,ans,c)
if bflag[i][j]==1 or board[i][j] not in c:
return False
else:
newc = c[board[i][j]]
if 'flag' in newc:
temp = word+board[i][j]
if temp not in ans:
ans.append(temp)
bflag[i][j]=1
if i>0:
if dfs(newc,i-1,j,bflag,word+board[i][j]):
return True
if j<xlen-1:
if dfs(newc,i,j+1,bflag,word+board[i][j]):
return True
if j>0:
if dfs(newc,i,j-1,bflag,word+board[i][j]):
return True
if i<ylen-1:
if dfs(newc,i+1,j,bflag,word+board[i][j]):
return True
return False
wor = ''
bflag=[]
for i in range(0, ylen):
tmp = []
for j in range(0, xlen):
tmp.append(0)
bflag.append(tmp)
for i in range(len(board)):
for j in range(len(board[0])):
#print(i,j)
dfs(ptree.root,i,j,bflag,wor)
return ans
class Trie(object):
def __init__(self):
self.root = {}
def insert(self, word):
"""
Inserts a word into the trie.
:type word: str
:rtype: void
"""
curNode = self.root
for i in word:
if i not in curNode:
curNode[i] = {}
curNode = curNode[i]
curNode["#"] = True
class Solution:
def findWords(self, board, words):
"""
:type board: List[List[str]]
:type words: List[str]
:rtype: List[str]
"""
row = len(board)
colum = len(board[0])
res = []
def find(x, y, word, TrieNode):
if x >= 0 and x < row and y >= 0 and y < colum and board[x][y] in TrieNode:
TrieNode = TrieNode[board[x][y]]
word += board[x][y]
if TrieNode.get("#", 9) == True:
res.append(word)
t = board[x][y]
board[x][y] = 3
find(x + 1, y, word, TrieNode)
find(x - 1, y, word, TrieNode)
find(x, y + 1, word, TrieNode)
find(x, y - 1, word, TrieNode)
board[x][y] = t
root = Trie()
tmp = set()
for i in words:
root.insert(i)
tmp.add(i[0])
for i in range(row):
for j in range(colum):
if board[i][j] in tmp:
find(i, j, "", root.root)
return list(set(res))
将代码单独放入spyder中运行,记录运行时间,发现时间差了约100倍。
总结了别人代码的优点
其中主要是因为第一个问题,所以还是要注意闭包的使用!!!!