日常系列LeetCode《19·BFS 和 DFS》

Posted 常某某的好奇心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日常系列LeetCode《19·BFS 和 DFS》相关的知识,希望对你有一定的参考价值。

数据规模->时间复杂度

<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(logn),o(1)

内容

lc 589 :N 叉树的前序遍历
https://leetcode.cn/problems/n-ary-tree-preorder-traversal/
提示:
节点总数在范围 [0, 104]内
0 <= Node.val <= 104
n 叉树的高度小于或等于 1000
进阶:
递归法很简单,你可以使用迭代法完成此题吗?

#方案一:迭代
"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        if not root:return []
        #
        res=[]
        stack=list()
        stack.append(root)
        while stack:
            curr=stack.pop()
            res.append(curr.val)
            #key
            for i in range(len(curr.children)-1,-1,-1):
                stack.append(curr.children[i])
        #
        return res
#方案二:递归
"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        if not root:return []
        #
        res=[]
        self.dfs(root,res)
        return res
    
    def dfs(self,node,res):
        if not node:return
        res.append(node.val)
        #key
        for children in node.children:
            self.dfs(children,res)
        # for i in range(len(node.children)):
        #     self.dfs(node.children[i],res)

lc 590 :N 叉树的后序遍历
https://leetcode.cn/problems/n-ary-tree-postorder-traversal/
提示:
节点总数在范围 [0, 104] 内
0 <= Node.val <= 104
n 叉树的高度小于或等于 1000
进阶:
递归法很简单,你可以使用迭代法完成此题吗?

#方案一:迭代
"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        if not root:return []
        res=list()
        stack=[] #list()
        stack.append(root)
        
        while stack:
            curr=stack.pop()
            res.append(curr.val)
            #
            for childnode in curr.children:
                stack.append(childnode) #key
        res.reverse()
        return res
        
#方案二:递归
"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        res=[]
        self.dfs(root,res)
        return res

    def dfs(self,node,res):
        if not node:return
        #
        for child in node.children:
            self.dfs(child,res)
        res.append(node.val)

lc 429 :N 叉树的层序遍历
https://leetcode.cn/problems/n-ary-tree-level-order-traversal/
提示:
树的高度不会超过 1000
树的节点总数在 [0, 10^4] 之间

#方案一:BFS
"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root:return []
        res=[]
        queue=deque()
        queue.append(root)
        while queue:
            level_nodes_val=[]
            for i in range(len(queue)):
                curr=queue.popleft()
                level_nodes_val.append(curr.val) #key
                for child in curr.children:
                    queue.append(child)
            res.append(level_nodes_val)
        return res

#方案二:DFS
"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        res=[]
        self.dfs(root,0,res)
        return res
    
    def dfs(self,node,currlevel,res):
        if not node:return []
        #key
        if len(res)-1 <currlevel:
            res.append([node.val])
        else:
            res[currlevel].append(node.val)
        #
        for child in node.children:
            self.dfs(child,currlevel+1,res)

lc 690 :员工的重要性
https://leetcode.cn/problems/employee-importance/
提示:
一个员工最多有一个 直系 领导,但是可以有多个 直系 下属
员工数量不超过 2000 。

#方案一:DFS-前序
"""
# Definition for Employee.
class Employee:
    def __init__(self, id: int, importance: int, subordinates: List[int]):
        self.id = id
        self.importance = importance
        self.subordinates = subordinates
"""

class Solution:
    def getImportance(self, employees: List['Employee'], id: int) -> int:
        self.id_map=emp.id:emp for emp in employees #key:id-emp
        self.total=0 #key
        self.dfs(id)
        return self.total
    
    def dfs(self,id):
        emp=self.id_map[id]
        if not emp:return
        #
        self.total+=emp.importance
        #
        for sub_emp_id in emp.subordinates:
            self.dfs(sub_emp_id)

#方案二:DFS-后序
"""
# Definition for Employee.
class Employee:
    def __init__(self, id: int, importance: int, subordinates: List[int]):
        self.id = id
        self.importance = importance
        self.subordinates = subordinates
"""

class Solution:
    def getImportance(self, employees: List['Employee'], id: int) -> int:
        self.id_map=emp.id:emp for emp in employees #key:id-emp
        return self.dfs(id)
    
    def dfs(self,id):
        emp=self.id_map[id]
        if not emp:return 0
        #dfs的时候(self.total=0)先累加子节点值,最后在加根节点(root.importance)
        self.total=0  #key:注意位置,
        for sub_emp_id in emp.subordinates:
            self.total+=self.dfs(sub_emp_id) 
            
        return emp.importance+self.total


#方案三:BFS
"""
# Definition for Employee.
class Employee:
    def __init__(self, id: int, importance: int, subordinates: List[int]):
        self.id = id
        self.importance = importance
        self.subordinates = subordinates
"""

class Solution:
    def getImportance(self, employees: List['Employee'], id: int) -> int:
        self.id_map=emp.id:emp for emp in employees #key:id-emp
        return self.bfs(id)
    
    def bfs(self,id):
        emp=self.id_map[id]
        if not emp:return 0
        #
        res=0
        queue=deque()
        queue.append(emp)
        while queue:
            levelres=0
            for i in range(len(queue)):
                curr=queue.popleft()
                levelres+=curr.importance
                for sub_id in curr.subordinates:
                    queue.append(self.id_map[sub_id]) #key
            res+=levelres
        return res

图的 DFS 和 BFS:key-遍历过程中,设置节点访问

floodfill 算法基础



#数组二维转一维
#数组一维转二维度
#二维数组的四联通
#二维数组的八联通
#保证索引访问合法

lc 733 :图像渲染
https://leetcode.cn/problems/flood-fill/
提示:
m == image.length
n == image[i].length
1 <= m, n <= 50
0 <= image[i][j], newColor < 216
0 <= sr < m
0 <= sc < n

#方案一:DFS
class Solution:
    def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]:
        self.dirs=[[-1,0],[1,0],[0,-1],[0,1]]
        self.image=image
        self.visited=[[False]*len(self.image[0]) for _ in range(len(self.image))]
        self.oldcolor=self.image[sr][sc]
        
        self.dfs(sr,sc,color)
        return image
    
    def inarea(self,row,col):
        return row>=0 and row<len(self.image) and col>=0 and col<len(self.image[0])
    
    def dfs(self,row,col,newcolor):
        #终止条件
        if not self.inarea(row,col) or self.image[row][col]!=self.oldcolor:
            return
        #
        self.image[row][col]=newcolor
        self.visited[row][col]=True
        for dir in self.dirs: 
            next_row=row+dir[0]
            next_col=col+dir[1]
            if self.inarea(next_row,next_col):
                if not self.visited[next_row][next_col]: 
                    self.dfs(next_row,next_col,newcolor)
#方案二:BFS
class Solution:
    def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]:
        self.image=image
        self.old_color=image[sr][sc]
        if self.old_color == color:  #key
            return image

        self.dirs=[[0,1],[0,-1],[1,0],[-1,0]]
        self.bfs(sr,sc,color)
        return self.image
    
    def inarea(self,row,col):
        return row>=0 and row<len(self.image) and col>=0 and col<len(self.image[0])

    def bfs(self,row,col,newcolor): 
        queue=deque()
        queue.append([row,col])
        self.image[row][col]=newcolor
        while queue:
            curr=queue.popleft()
            #
            for dir in self.dirs: #key1
                nextrow=dir[0]+curr[0]
                nextcol=dir[1]+curr[1]
                if self.inarea(nextrow,nextcol) and self.image[nextrow][nextcol]==self.old_color:
                    queue.append([nextrow,nextcol]) #key1
                    self.image[nextrow][nextcol]=newcolor

lc 463 :岛屿的周长
https://leetcode.cn/problems/island-perimeter/
提示:
row == grid.length
col == grid[i].length
1 <= row, col <= 100
grid[i][j] 为 0 或 1
岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连(只有一个岛

#方案一:DFS-前序
class Solution:
    def islandPerimeter(self, grid: List[List[int]]) -> int:
        self.grid=grid
        self.dirs=[[-1,0],[1,0],[0,-1],[0,1]]
        self.visited=[[False]*len(grid[0]) for _ in range(len(grid))]
        #
        self.ans=0
        for i in range(len(self.grid)):
            for j in range(len(self.grid[0])):
                if self.grid[i][j]==1:
                    self.dfs(i,j)
                    return self.ans
    
    def inarea(self,row,col):
        return row>=0 and row<len(self.grid) and col>=0 and col<len(self.grid[0])

    def dfs(self,row,col):
        if not self.inarea(row,col) or self.grid[row][col]==0 or self.visited[row][col]:
            return
        #
        self.visited[row][col]=True
        for dir in self.dirs:
            nextrow=dir[0]+row
            nextcol=dir[1]+col
            #key:计边长
            if not self.inarea(nextrow,nextcol) or self.grid[nextrow][nextcol]==0:
                self.ans+=1
            elif not self.visited[nextrow][nextcol]:
                self.dfs(nextrow,nextcol)
            
#方案二:DFS-后序
class Solution:
    def islandPerimeter(self, grid: List[List[int]]) -> int:
        self.grid=grid
        self.dirs=[[-1,0],[1,0],[0,-1],[0,1]]
        self.visited=[[False]*len(grid[0]) for _ in range(len(grid))]
        #
        for i in range(len(self.grid)):
            for j in range(len(self.grid[0])):
                if self.grid[i][j]==以上是关于日常系列LeetCode《19·BFS 和 DFS》的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode刷题之BFS和DFS

LeetCode 1302 层数最深叶子节点的和[BFS DFS] HERODING的LeetCode之路

leetcode 200. 岛屿数量(dfs||bfs)

LeetCode 0623.在二叉树中增加一行:DFS / BFS

LeetCode

leetcode之最短路径+记忆化dfs+bfs+动态规划刷题总结