天天刷leetcode——BFS和DFS其应用

BFS(广度优先遍历)

B队 使用队列实现
由于图会存在回路和重复值。因此需要有一个判断重复的列表visited。对于树,visited列表可以省略。

如果不需要确定当前遍历到了哪一层,BFS代码如下

def BFS(graph,start,end):
	queue = []
	queue.append([start])
	visited.append(start)
	while queue:
		# 队列第一个元素出去
		node = queue.pop(0)
		# 访问列表添加元素
		visited.append(node)
		# 处理这个节点
		process(node)
		# 产生后续节点,并且判断后继节点是否被访问
		nodes = generate_related_nodes(node)
		# 后续节点进队列
		queue.append(nodes)
		

如果需要知道遍历到那一层了,需要增加level表示当前遍历到二叉树中的哪一层了,也可以理解为在一个图中,现在已经走了多少步了。size表示在当前遍历层有多少个元素,也就是队列中的元素数,我们把这些元素一次性遍历完,即把当前层的所有元素都向外走了一步。
代码如下:

level = 0
result = []
while queue 不空:
    size = len(queue)
    tmp =[]
    for i in range(size):
        node = queue.pop(0)
        tmp.append(node.val)
        for 节点 in cur的所有相邻节点:
            if 该节点有效且未被访问过:
                queue.append(该节点)
    result.append(ls)
   	level += 1

BFS和DFS最主要的区别是:BFS找到的路径一定是最短的,但代价就是空间复杂度比DFS高很大。
BFS出现的场景:问题的本质就是在图中找到从起点start到终点end的最近距离。

应用题1——leetcode111最小深度

分析:起点就是root根节点,终点就是靠近根节点的那个叶子节点。当当前节点的left和right都是None就是,那么这个节点就是叶子节点。

   def minDepth(self, root: TreeNode) -> int:
        if root is None:
            return 0
        level = 1
        queue = [root]
        while queue:
            n = len(queue)
            for i in range(n):
                cur = queue.pop(0)
                if cur.left == cur.right == None:
                    return level
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            level += 1
        return level

应用题2——752. 打开转盘锁

1.不考虑限制条件,穷尽所有密码组合,整个转动过程就是一个图。每个节点的有八个相邻节点(‘0000’->‘0100’,‘0001’,‘0010’,‘1000’,‘0900’,‘9000’,‘0009’,‘0090’。求图中的最短距离。所以可以用BFS求解。

def openLock(self, deadends: List[str], target: str) -> int:
        def plusOne(s,j):
            s = list(s)
            if s[j] == '9':
                s[j] = '0'
            else:
                s[j] = str(int(s[j])+ 1)
            return ''.join(s)
        # 向下波动一次
        def minusOne(s,j):
            s = list(s)
            if s[j] == '0':
                s[j] = '9'
            else:
                s[j] = str(int(s[j])- 1)
            return ''.join(s)

        # python在set中查找的时间复杂度为o(1)
        deadends = set(deadends)
        visited = set()
        q = ['0000']
        # 从起点开始BFS
        step = 0
        visited.add('0000')
        while q:
            n = len(q)
            for i in range(n):
                cur = q.pop(0)
                # 判断是否到达终点
                if cur == target:
                    return step
                # 跳过死亡密码
                if cur in deadends:
                    continue
                # 将一个节点的未遍历相邻节点加入队列
                for j in range(4):
                    up = plusOne(cur,j)
                    down = minusOne(cur,j)
                    if up not in visited:
                        q.append(up)
                        visited.add(up)
                    if down not in visited:
                        q.append(down)
                        visited.add(down)
            step += 1
        return -1
	

应用3—— leetcode102——二叉树的层次遍历

    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if root is None:
            return []
        result= []
        queue = [root]
        while queue:
            size = len(queue)
            tmp = []
            for i in range(size):
                node = queue.pop(0)
                tmp.append(node.val)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            result.append(tmp)
        return result

时间复杂度O(n)
在这里插入图片描述

2. DFS( 深度优先遍历)

递归:

visited = set()
def dfs(node,visited):
	visited.append(node)
	# 处理访问到的节点
	for next_node in node.children():
		if not next_node in visited:
			dfs(next_node,visited)

非递归:
用stack实现

def dfs(tree):
	if tree.root is None:
		return []
	visited,stack = [],[tree.root]
	while stack:
		node = stack.pop()
		visited.append(node)
		process(node)
		nodes = generate_related_nodes(node)
		stack.insert(0,nodes)

应用题—— 二叉树的最大深度和最小深度

(1) leetcode55最大深度
递归

    def maxDepth(self, root: TreeNode) -> int:
        if root is None:
            return 0
        return 1 + max(self.maxDepth(root.left),self.maxDepth(root.right))

在这里插入图片描述
非递归,使用BFS

    def maxDepth(self, root: TreeNode) -> int:
        if root is None:
            return 0
        level = 0
        queue = [root]
        while queue:
            size = len(queue)
            for i in range(size):
                node = queue.pop(0)
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            level += 1
        return level

在这里插入图片描述

(2) leetcode111最小深度

    def minDepth(self, root: TreeNode) -> int:
        if root is None:
            return 0
        # 没有左子树,直接return 1 + 右子树
        if root.left is None:
            return 1 + self.minDepth(root.right)
        # 没有右子树,直接return 1 + 左子树
        if root.right is None:
            return 1 + self.minDepth(root.left)
        leftM = self.minDepth(root.left)
        rightM = self.minDepth(root.right)
        result = 1+ min(leftM,rightM)
        return result

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值