题目描述
给定一个bottom字符串,和allowed数组。
allowed数组中每一个字符串都含有一个三元组(A,B,C),表示一种规则:C的左孩子可以是A,右孩子可以是B。
判断给定bottom和allowed,是否能构造一个金字塔的结构,满足allowed的规则,并且金字塔的最后一层就是bottom字符串。
例子
Example 1:
Input: bottom = “XYZ”, allowed = [“XYD”, “YZE”, “DEA”, “FFF”]
Output: true
可以形成如下所示的金字塔:
A
/ \
D E
/ \ / \
X Y Z
Example 2:
Input: bottom = “XXYX”, allowed = [“XXX”, “XXY”, “XYX”, “XYY”, “YXZ”]
Output: false
注意:可以存在三元组 (A, B, C) 和 (A, B, D),其中 C != D.
思想
在当前bottom的基础上,递推上一层的结点,直到结点只包含1个 → 构造完成。
1)递推上一层:建一个 dic 拆分三元组,例如(X,Y,Z),则记录dic[(X,Y)] = [z];
2)allLists 存储上一层可能包含的结点。例如[[‘X’,‘Y’], [‘Z’]],表示上一层可能为’XZ’或’YZ’;
3)helper函数用来组合,在 allLists 基础上构造上一层可能的状态。例如[[‘X’,‘Y’], [‘Z’]] → [‘XZ’, ‘YZ’],(其中combs = [‘XZ’, ‘YZ’]表示上一层可能的状态);
4)省时间,cache 存储已判断过的bottom,记录以该bottom为底,是否可构造金字塔。例如在递归过程中,'XZZ’可以构造金字塔,则 cache[‘XZZ’] = True,下次再遇到’XZZ’就无需判断了~
解法
全组合采用BFS,而不是DFS。
class Solution(object):
def pyramidTransition(self, bottom, allowed):
"""
:type bottom: str
:type allowed: List[str]
:rtype: bool
"""
self.dic = {}
self.cache = {}
allowed = set(allowed)
for allow in allowed:
if allow[:2] not in self.dic:
self.dic[allow[:2]] = [allow[-1]]
else:
self.dic[allow[:2]].append(allow[-1])
return self.dfs(bottom)
def dfs(self, bottom):
if len(bottom) == 2:
return bottom in self.dic
if bottom in self.cache:
return self.cache[bottom]
allLists = []
for i in range(len(bottom)-1):
if bottom[i:i+2] not in self.dic:
self.cache[bottom] = False
return False
allLists.append(self.dic[bottom[i:i+2]])
combs = self.helper(allLists)
for comb in combs:
if self.dfs(comb):
self.cache[comb] = True
return True
self.cache[bottom] = False
return False
def helper(self, allLists):
queue = ['']
for List in allLists:
for _ in range(len(queue)):
node = queue.pop(0)
for c in List:
queue.append(node + c)
return queue
原始:全组合采用的DFS,TLE
class Solution(object):
def pyramidTransition(self, bottom, allowed):
"""
:type bottom: str
:type allowed: List[str]
:rtype: bool
"""
self.dic = {}
self.cache = {}
for allow in allowed:
if allow[:2] not in self.dic:
self.dic[allow[:2]] = [allow[2]]
else:
self.dic[allow[:2]] += [allow[2]]
return self.dfs(bottom)
def dfs(self, bottom):
if len(bottom) == 1:
return True
if bottom in self.cache:
return self.cache[bottom]
allLists = []
for i in range(len(bottom)-1):
if bottom[i:i+2] not in self.dic:
self.cache[bottom] = False
return False
allLists.append(self.dic[bottom[i:i+2]])
combs = []
self.helper(allLists, '', combs)
for comb in combs:
if self.dfs(comb):
self.cache[comb] = True
return True
self.cache[bottom] = False
return False
def helper(self, allLists, temp, combs):
if not allLists:
combs.append(temp)
return
for List in allLists:
for c in List:
self.helper(allLists[1:], temp + c, combs)
题目描述
给定一个2D网格和一个单词word,判断word是否存在于网格中。
单词可以由顺序相邻的单元字母重构(水平相邻和垂直相邻),用过的单元不能重复使用。
例子
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]
Given word = “ABCCED”, return true.
Given word = “SEE”, return true.
Given word = “ABCB”, return false.
思想
比较经典的路径搜索回溯。
1)首先,主体函数的两层for循环 → 确定路径的起点;
2)DFS中
截止条件:已遍历完word;
主体部分:当前位置是否有效(0 <= x < m and 0 <= y < n),且未被访问过(not visited[x][y]),且和word匹配(board[x][y] == word[0])?是的话,搜索上、下、左、右4个位置。其中visited是标记该位置是否被访问过。
解法
class Solution(object):
def exist(self, board, word):
"""
:type board: List[List[str]]
:type word: str
:rtype: bool
"""
m, n = len(board), len(board[0])
visited = [[False] * n for _ in range(m)]
for x in range(m):
for y in range(n):
if self.dfs(board, word, m, n, x, y, visited):
return True
return False
def dfs(self, board, word, m, n, x, y, visited):
if not word:
return True
if 0 <= x < m and 0 <= y < n and not visited[x][y] and board[x][y] == word[0]:
visited[x][y] = True
if (self.dfs(board, word[1:], m, n, x+1, y, visited)
or self.dfs(board, word[1:], m, n, x-1, y, visited)
or self.dfs(board, word[1:], m, n, x, y+1, visited)
or self.dfs(board, word[1:], m, n, x, y-1, visited)):
return True
visited[x][y] = False
return False