DFS+回溯專題14 - leetcode756. Pyramid Transition Matrix/79. Word Search - Medium
756. Pyramid Transition Matrix
題目描述
給定一個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
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)
79. Word Search
題目描述
給定一個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