第六章二叉树——层序遍历

吾日三省吾身

还记得梦想吗

正在努力实现它吗

可以坚持下去吗

目录

吾日三省吾身

力扣题号:102. 二叉树的层序遍历 - 力扣(LeetCode)

题目描述

Java解法:二叉树的层序遍历

实现思路

注意事项

代码

C++解法:使用两个队列

实现思路

注意事项

代码

总结



力扣题号:102. 二叉树的层序遍历 - 力扣(LeetCode)

注:下述题目描述和示例均来自力扣

题目描述

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

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

提示:

  • 树中节点数目在范围 [0, 2000] 内
  • -1000 <= Node.val <= 1000

Java解法:二叉树的层序遍历

思路如下:

  • 创建一个二维列表 res 用于存储最终结果。
  • 若根节点为空,直接返回空列表 res
  • 使用 ArrayDeque 实现的双端队列 deque,将根节点放入队列。
  • 进入循环,每次循环处理一层的节点。
    • 记录当前层需要遍历的节点数量 len,以便在循环中遍历当前层的节点。
    • 创建一个列表 one 用于存储当前层的节点值。
    • 在内部循环中,弹出队列中的节点,并将其值添加到 one 列表中。
    • 如果节点的左子节点存在,则将左子节点加入队列。
    • 如果节点的右子节点存在,则将右子节点加入队列。
    • 循环结束后,将 one 列表加入 res 列表。
  • 最终返回层序遍历的结果 res

实现思路

        该算法通过使用双端队列(Deque)实现的队列来进行层序遍历。在每一层遍历时,记录当前层节点数以确保只遍历当前层的节点,并将节点值存储在一个列表中。将每一层的列表加入最终结果列表,最终返回完整的层序遍历结果。

注意事项

  • 为了保证队列的长度不会在遍历过程中发生变化,使用一个变量 len 来记录每一层需要遍历的节点数。
  • 算法使用了广度优先搜索(BFS)的思想,确保同一层的节点先被遍历,从而实现层序遍历的效果。

代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> res = new ArrayList<>();
        if (root == null){
            return res;
        }

        Deque<TreeNode> deque = new ArrayDeque<>();
        deque.offer(root);

        while (!deque.isEmpty()){
            // 记录一下这一层需要遍历的层数
            // 为什么要在这里记录,因为队列的弹出会导致长度变化的
            int len = deque.size();
            // 定义一个list记录这一层的全部数据
            List<Integer> one = new ArrayList<>();
            for (int i = 0; i < len; i++) {
                // 获取一个根节点
                TreeNode node = deque.poll();
                one.add(node.val);
                // 判断是左右节点是否存在,如果存在就加入队列,下一层使用
                if (node.left != null){
                    deque.offer(node.left);
                }
                if (node.right != null){
                    deque.offer(node.right);
                }
            }
            // 一次len的循环就可以完成一层,一个list,加入res中即可
            res.add(one);
        }
        return res;
    }
}

不算太快哈,也没有打败全世界的人


C++解法:使用两个队列

思路如下:

  • 创建一个二维向量 result 用于存储最终结果。
  • 若根节点为空,直接返回空向量 result
  • 使用两个队列 currentLevelnextLevel 分别表示当前层和下一层的节点。
  • 将根节点放入 currentLevel 队列。
  • 进入循环,每次循环处理一层的节点。
    • 创建一个向量 levelValues 用于存储当前层的节点值。
    • 在内部循环中,弹出 currentLevel 队列中的节点,并将其值添加到 levelValues 向量中。
    • 如果节点的左子节点不为空,将其加入 nextLevel 队列。
    • 如果节点的右子节点不为空,将其加入 nextLevel 队列。
    • 循环结束后,将 levelValues 向量加入 result 向量。
    • 通过交换 currentLevelnextLevel,准备处理下一层的节点。
  • 最终返回层序遍历的结果 result

实现思路

        该算法通过使用两个队列来避免在每一层的循环中进行队列的长度计算,提高了代码的效率。在每一层遍历时,使用两个队列交替存储当前层和下一层的节点,通过交换队列减少了不必要的操作。

注意事项

  • 使用两个队列来交替存储当前层和下一层的节点,避免在每一层的循环中进行队列的长度计算,提高了代码的效率。
  • 代码使用了队列来实现广度优先搜索(BFS)的思想,确保同一层的节点先被遍历,从而实现层序遍历的效果。

巧妙吧~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;

        if (!root) {
            return result;
        }

        queue<TreeNode*> currentLevel;
        queue<TreeNode*> nextLevel;

        currentLevel.push(root);

        while (!currentLevel.empty()) {
            vector<int> levelValues;

            while (!currentLevel.empty()) {
                TreeNode* node = currentLevel.front();
                currentLevel.pop();

                levelValues.push_back(node->val);

                if (node->left) {
                    nextLevel.push(node->left);
                }

                if (node->right) {
                    nextLevel.push(node->right);
                }
            }

            result.push_back(levelValues);
            swap(currentLevel, nextLevel);
        }

        return result;
    }
};

总结

       拿下喽,java的两个队列代码我就不提供了,反正已经拿下喽~~~

ヾ( ̄▽ ̄)Bye~Bye~

  • 27
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WenJGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值