DFS+回溯专题14 - leetcode756. Pyramid Transition Matrix/79. Word Search - Medium

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a786150017/article/details/85047512

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函数用来组合,在 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)

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

猜你喜欢

转载自blog.csdn.net/a786150017/article/details/85047512