力扣刷题-二叉树-二叉树的层序遍历(相关题目总结)

思路

层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。
而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。
使用队列实现二叉树广度优先遍历,动画如下:

这样就实现了层序从左到右遍历二叉树。
参考:https://www.programmercarl.com/0102.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86.html

102 层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
image.png

利用长度法

# 注意结果的返回形式是每层作为一个列表
# 法一 长度法

from collections import deque
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        # 注意判断是否为空
        if not root:
            return []
        result = [] # 最终结果列表 里面会存储每一层的遍历结果
        queue = deque([root]) # 采用队列来模拟
        while queue: # 当queue为空 终止
            level_result = [] # 每一层结果
            for _ in range(len(queue)): # queue中记录的是每一层进入队列的元素 所以遍历其长度 来获取元素值
                cur = queue.popleft()
                level_result.append(cur.val)
                if cur.left: # 左孩子 就是第二层了
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(level_result)
        return result

递归法

每次写递归,都按照这三要素来写,可以保证大家写出正确的递归算法!
确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。
确定终止条件: 写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。
确定单层递归的逻辑: 确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。

# 法二 递归法
from collections import deque
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution(object):
    def levelOrder(self, root):
        if not root:
            return []
        levels = []
        self.helper(root, 0, levels)
        return levels
    
    def helper(self, node, level, levels):
        if not node:
            return
        if len(levels) == level:
            levels.append([]) # 每层开始 用[]初始化
        levels[level].append(node.val)
        self.helper(node.left, level+1, levels)
        self.helper(node.right, level+1, levels)

确定递归函数的参数和返回值:当前节点;第几层,结果存储列表
确定终止条件:当当前节点不存在的时候 直接return(终止本次)
确定单层递归的逻辑:
if len(levels) == level:
levels.append([]) # 每层开始 用[]初始化
levels[level].append(node.val)

107. 二叉树的层序遍历 II

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
示例 1:
image.png
输入:root = [3,9,20,null,null,15,7]
输出:[[15,7],[9,20],[3]]
其实相当于就是上一题结果做一下翻转。

from collections import deque

class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution(object):
    def levelOrderBottom(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root:
            return []
        result = []
        queue = deque([root])
        while queue:
            level_result = []
            for _ in range(len(queue)):
                cur = queue.popleft()
                level_result.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(level_result)
        return result[::-1]

199. 二叉树的右视图

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例 1:
image.png
输入: [1,2,3,null,5,null,4]
输出: [1,3,4]
思路:其实就是层序遍历每一层遍历结果的最后一个元素

from collections import deque
class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution(object):
    def rightSideView(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if not root:
            return []
        levels = []
        self.helper(root, 0, levels)
        result = []
        for item in levels:
            result.append(item[len(item)-1])
        return result

    def helper(self, node, level, levels):
        if not node:
            return 
        if len(levels) == level:
            levels.append([])
        levels[level].append(node.val)
        self.helper(node.left, level+1, levels)
        self.helper(node.right, level+1, levels)

637. 二叉树的层平均值

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。
示例 1:
image.png
输入:root = [3,9,20,null,null,15,7]
输出:[3.00000,14.50000,11.00000]
解释:第 0 层的平均值为 3,第 1 层的平均值为 14.5,第 2 层的平均值为 11 。
因此返回 [3, 14.5, 11]
思路:就是对每一层结果 取平均 注意需要用float!!!


from collections import deque

class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution(object):
    def averageOfLevels(self, root):
        """
        :type root: TreeNode
        :rtype: List[float]
        """
        if not root:
            return []
        result = []
        queue = deque([root])
        while queue:
            level_result = []
            for _ in range(len(queue)):
                cur = queue.popleft()
                level_result.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(level_result)
        final = [(sum(item)/float(len(item))) for item in result] # 注意要加上float 因为python中 / 是整除
        return final 

429. N 叉树的层序遍历

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。
示例 1:
image.png
输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]
思路:N叉树 每个节点存在多个孩子 所以要采用遍历方式

from collections import deque 

class Node(object):
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children


class Solution(object):
    def levelOrder(self, root):
        """
        :type root: Node
        :rtype: List[List[int]]
        """
        if not root:
            return []
        result = []
        queue = deque([root])
        while queue:
            level_result = []
            for _ in range(len(queue)):
                node = queue.popleft()
                level_result.append(node.val)
                for child in node.children: # 因为有多个孩子 所以采用遍历方式
                    queue.append(child)
            result.append(level_result)
        return result

时间复杂度:O(n),其中 n 是树中包含的节点个数。在广度优先搜索的过程中,我们需要遍历每一个节点恰好一次。
空间复杂度:O(n),即为队列需要使用的空间。在最坏的情况下,树只有两层,且最后一层有 n−1 个节点,此时就需要 O(n) 的空间。

515. 在每个树行中找最大值

给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。
示例1:
image.png
输入: root = [1,3,2,5,3,null,9]
输出: [1,3,9]

思路:就是求每一层遍历结果的最大值

class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution(object):
    def largestValues(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if not root:
            return []
        result = []
        queue = deque([root])
        while queue:
            level_result = []
            for _ in range(len(queue)):
                cur = queue.popleft()
                level_result.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(level_result)
        final = [max(item) for item in result] # 求最大
        return final 

(※)116. 填充每个节点的下一个右侧节点指针

给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
示例 1:
image.png
输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,‘#’ 标志着每一层的结束。

# # 注意节点定义
class Node(object):
    def __init__(self, val=0, left=None, right=None, next=None):
        self.val = val
        self.left = left
        self.right = right 
        self.next = next # 多了一个next

from collections import deque

class Solution:
    def connect(self, root):
        if not root:
            return root # 因为最终返回的是整棵树
        # 初始化队列同时将第一层节点加入队列中,即根节点
        Q = collections.deque([root])
        # 外层的 while 循环迭代的是层数
        while Q:
            # 记录当前队列大小
            size = len(Q)
            # 遍历这一层的所有节点
            for i in range(size):
                # 从队首取出元素
                node = Q.popleft()
                # 连接 比较巧妙
                if i < size - 1: # 题目说了 初始状态下 所有的Next指针都设置为 null
                    node.next = Q[0] # 比如2出来 指向队列里面第一个元素 就是3
                # 拓展下一层节点
                if node.left:
                    Q.append(node.left)
                if node.right:
                    Q.append(node.right)
        # 返回根节点
        return root

117 填充每个节点的下一个右侧节点指针 II

给定一个二叉树:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL 。
初始状态下,所有 next 指针都被设置为 NULL 。
示例 1:
image.png
输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),‘#’ 表示每层的末尾。
思路:其实和上一题是一样,上一题是完美/全二叉树,本题不是,但是是一样的做法。

from collections import deque

class Node(object):
    def __init__(self, val=0, left=None, right=None, next=None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next

class Solution(object):
    def connect(self, root):
        """
        :type root: Node
        :rtype: Node
        """
        if not root:
            return root
        queue = deque([root])
        while queue:
            size = len(queue)
            for i in range(size):
                cur = queue.popleft()
                if i < size - 1:
                    cur.next = queue[0]
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
        return root   

104. 二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例 1:
image.png
输入:root = [3,9,20,null,null,15,7]
输出:3
思路:按照层序遍历 有多少层(最大深度)即 有多少个嵌套列表

层次遍历
from collections import deque

class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        result = []
        queue = deque([root])
        while queue:
            level_result = []
            for _ in range(len(queue)):
                cur = queue.popleft()
                level_result.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            result.append(level_result)
        return len(result) # 里面多少嵌套列表 即为最大深度
递归

递归第一点:参数就是传入树的根节点,返回就返回这棵树的深度,所以返回值为int类型。
递归第二点:如果为空节点的话,就返回0,表示高度为0。
递归第三点:
**先求它的左子树的深度,再求右子树的深度,最后取左右深度最大的数值 再+1 **(加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。(也就是高度)

class solution:
    def maxdepth(self, root: treenode) -> int:
        return self.getdepth(root)
    def getdepth(self, node):
        if not node:
            return 0
        leftdepth = self.getdepth(node.left)
        rightdepth = self.getdepth(node.right)
        depth = max(leftdepth, rightdepth) + 1
        return depth

精简版:

class solution:
    def maxdepth(self, root: treenode) -> int:
        if not root:
            return 0
        return 1 + max(self.maxdepth(root.left), self.maxdepth(root.right))

559. N 叉树的最大深度

层次遍历

给定一个 N 叉树,找到其最大深度。
最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。
N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔(请参见示例)。
示例 1:
image.png
输入:root = [1,null,3,2,4,null,5,6]
输出:3

# Definition for a Node.
class Node(object):
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children


from collections import deque
class Solution(object):
    def maxDepth(self, root):
        """
        :type root: Node
        :rtype: int
        """
        if not root:
            return 0
        result = []
        queue = deque([root])
        while queue:
            level_result = []
            for _ in range(len(queue)):
                cur = queue.popleft()
                level_result.append(cur.val)
                for child in cur.children: # 特别之处
                    queue.append(child)
            result.append(level_result)
        return len(result)
递归
class Solution:
    def maxDepth(self, root: 'Node') -> int:
        if not root:
            return 0
        max_depth = 1
        for child in root.children:
            max_depth = max(max_depth, self.maxDepth(child) + 1)
        
        return max_depth

(※)111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
示例 1:
image.png
输入:root = [3,9,20,null,null,15,7]
输出:2

层序遍历法
# 层序遍历法
class Solution(object):
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        queue = deque([(root, 1)]) # 每个元素是元组 一个是树元素值 一个是最小深度 比较巧妙

        while queue:
            cur, min_depth = queue.popleft()
            if not cur.left and not cur.right:
                return min_depth
            if cur.left:
                queue.append((cur.left, min_depth+1))
            if cur.right:
                queue.append((cur.right, min_depth+1))
        return 0

时间复杂度:O(N) 因为每个结点会访问一次
空间复杂度:O(N)在层序遍历法中空间复杂度主要取决于队列的开销,队列中的元素个数不会超过树的节点数。

递归法

注意这块和最大深度不一样,如下是错误代码:
image.png
这个代码就犯了此图中的误区:
image.png
如果这么求的话,没有左孩子的分支会算为最短深度。
所以,如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。 最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。

# 递归法
class Solution(object):
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        return self.getDepth(root)
    
    def getDepth(self, node):
        if node is None:
            return 0
        leftDepth = self.getDepth(node.left)  # 左
        rightDepth = self.getDepth(node.right)  # 右
        
        # 当一个左子树为空,右不为空,这时并不是最低点
        if node.left is None and node.right is not None:
            return 1 + rightDepth
        
        # 当一个右子树为空,左不为空,这时并不是最低点
        if node.left is not None and node.right is None:
            return 1 + leftDepth
        
        result = 1 + min(leftDepth, rightDepth)
        return result

时间复杂度:O(N),其中 N 是树的节点数。对每个节点访问一次。
空间复杂度:O(N)/O(H) 其中 H 是树的高度。空间复杂度主要取决于递归时栈空间的开销,最坏情况下,树呈现链状,空间复杂度为 O(N)。平均情况下树的高度与节点数的对数正相关,空间复杂度为 O(log⁡N)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树层序遍历是一种广度优先搜索算法,通过逐层地从左到右访问所有节点,返回节点值的顺序。可以使用队列来实现层序遍历。具体思路如下: 1. 创建一个空的结果数组res和一个队列que,将根节点root放入队列que中。 2. 当队列que不为空时,执行以下操作: - 定义一个变量size,用于记录队列que的长度。 - 创建一个空的一维数组vec,用于记录当前层的节点值。 - 遍历0到size-1,执行以下操作: - 弹出队列que的头节点cur。 - 将cur的值cur->val添加到一维数组vec中。 - 若cur的左子节点不为空,则将cur的左子节点压入队列que中。 - 若cur的右子节点不为空,则将cur的右子节点压入队列que中。 - 将一维数组vec添加到结果数组res中。 3. 返回结果数组res作为层序遍历的结果。 以下是一段C++代码示例,实现了二叉树层序遍历: ``` vector<vector<int>> levelOrder(TreeNode* root) { vector<vector<int>> res; // 结果数组 queue<TreeNode*> que; if (root) que.push(root); while (!que.empty()) { int size = que.size(); // 记录队列的长度 vector<int> vec; for (int i = 0; i < size; i++) { TreeNode* cur = que.front(); que.pop(); vec.push_back(cur->val); if (cur->left) que.push(cur->left); if (cur->right) que.push(cur->right); } res.push_back(vec); } return res; } ``` 这段代码使用了一个队列que,利用队列的先进先出的特点,按照层序遍历的顺序将节点添加到结果数组res中。最后返回结果数组res即可得到二叉树层序遍历结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [力扣刷题 | 二叉树](https://download.csdn.net/download/weixin_38633083/13740772)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [力扣:102. 二叉树层序遍历](https://blog.csdn.net/qq_46111138/article/details/124895548)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值