JavaScript:二叉树(层序遍历)

news2024/7/6 18:53:41

二叉树的层序遍历

层序遍历:逐层地,从左到右访问所有节点
广度优先

文章目录

  • 二叉树的层序遍历
    • 102. 二叉树的层序遍历 - 力扣(LeetCode)
    • 107. 二叉树的层序遍历 II - 力扣(LeetCode)
    • 199. 二叉树的右视图 - 力扣(LeetCode)
    • 429. N 叉树的层序遍历 - 力扣(LeetCode)
    • 515. 在每个树行中找最大值 - 力扣(LeetCode)
    • 104. 二叉树的最大深度 - 力扣(LeetCode)
    • 111. 二叉树的最小深度 - 力扣(LeetCode)
    • 总结
    • 扩展

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

在这里插入图片描述
代码及思路分析

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
    // res存储结果  queue队列里面存储每层节点
    let res = [], queue = []
    queue.push(root)
    if(root === null) return res
    
    // 遍历当前层的所有节点
    while(queue.length!== 0) {
        // 记录当前层级节点数
        let length = queue.length
        // 存放每一层的节点
        let curLeverl = []
        for(let i = 0; i < length; i++) {
            // 弹出队列的节点,也就是当层的节点 从左到右
            let node = queue.shift
            // 弹出一个,并且把他的子节点压入队列,为了下一次的遍历
            curLeverl.push(node.val)
            // 存放当前层下一层的节点
            node.left && queue.push(node.left)
            node.right && queue.push(node.right)
        }
        // 把每一层的结果放到结果数组
        res.push(curLeverl)
    }
};

107. 二叉树的层序遍历 II - 力扣(LeetCode)

自底向上的层序遍历
思路:把上面一题的结果res数组反转一下就可以了,我们这里把当层的结果curLevel插入数组头部即可(上一题是push压入尾部)

/*
* @lc app=leetcode.cn id=107 lang=javascript
*
* [107] 二叉树的层序遍历 II
*/

// @lc code=start
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
*     this.val = (val===undefined ? 0 : val)
*     this.left = (left===undefined ? null : left)
*     this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[][]}
*/
var levelOrderBottom = function(root) {
   let res = [], queue = []
   // 第一排根先入队
   queue.push(root)
   if(root === null) return res

   while(queue.length != 0) {
       // 记录当层级节点数
       let len = queue.length
       // 存放每一层节点
       let curLevel = []
       for(let i = 0; i < len; i++) {
           // 弹出队里首位并且把当前节点的val压入到存放节点的数组
           let node = queue.shift()
           curLevel.push(node.val)
           // 当前层下一层的节点入队
           node.left && queue.push(node.left)
           node.right && queue.push(node.right)
       }
       // 从数组前头插入值,避免最后反转数组,减少运算时间
       res.unshift(curLevel);    
   }
   return res
};
// @lc code=end

199. 二叉树的右视图 - 力扣(LeetCode)

在这里插入图片描述

层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。

/*
 * @lc app=leetcode.cn id=199 lang=javascript
 *
 * [199] 二叉树的右视图
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var rightSideView = function(root) {
    //二叉树右视图 只需要把每一层最后一个节点存储到res数组
    let res = [], queue = [];
    queue.push(root);

    while(queue.length && root!==null) {
        // 记录当前层级节点个数
        let length = queue.length;
        while(length--) {
            let node = queue.shift();
            // length长度为0的时候表明到了层级最后一个节点
            if(!length) {
                res.push(node.val);
            }
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
    }

    return res;
};
// @lc code=end

429. N 叉树的层序遍历 - 力扣(LeetCode)

思路:
这道题依旧是模板题,只不过一个节点有多个孩子了

/*
 * @lc app=leetcode.cn id=429 lang=javascript
 *
 * [429] N 叉树的层序遍历
 */

// @lc code=start
/**
 * // Definition for a Node.
 * function Node(val,children) {
 *    this.val = val;
 *    this.children = children;
 * };
 */

/**
 * @param {Node|null} root
 * @return {number[][]}
 */
var levelOrder = function(root) {
    //每一层可能有2个以上,所以不再使用node.left node.right
    let res = [], queue = [];
    queue.push(root);

    while(queue.length && root!==null) {
        //记录每一层节点个数还是和二叉树一致
        let length = queue.length;
        //存放每层节点 也和二叉树一致
        let curLevel = [];
        while(length--) {
            let node = queue.shift();
            curLevel.push(node.val);

            //这里不再是 ndoe.left node.right 而是循坏node.children
           for(let item of node.children){
               item && queue.push(item);
           }
        }
        res.push(curLevel);
    }

    return res;   
};
// @lc code=end

515. 在每个树行中找最大值 - 力扣(LeetCode)

思路:
层序遍历,取每一层的最大值

/*
 * @lc app=leetcode.cn id=515 lang=javascript
 *
 * [515] 在每个树行中找最大值
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var largestValues = function(root) {
    //使用层序遍历
    let res = [], queue = [];
    queue.push(root);

    while(root !== null && queue.length) {
        //设置max初始值就是队列的第一个元素
        let max = queue[0].val;
        let length = queue.length;
        while(length--) {
            let node = queue.shift();
            max = max > node.val ? max : node.val;
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
        //把每一层的最大值放到res数组
        res.push(max);
    }

    return res;
};
// @lc code=end

104. 二叉树的最大深度 - 力扣(LeetCode)

思路:
使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
在二叉树中,一层一层的来遍历二叉树,记录一下遍历的层数就是二叉树的深度,如图所示:
[图片]

所以这道题的迭代法就是一道模板题,可以使用二叉树层序遍历的模板来解决的。

/*
 * @lc app=leetcode.cn id=104 lang=javascript
 *
 * [104] 二叉树的最大深度
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function(root) {
    // 最大的深度就是二叉树的层数
    if (root === null) return 0;
    let queue = [root];
    let height = 0;
    while (queue.length) {
        let n = queue.length;
        height++;
        for (let i=0; i<n; i++) {
            let node = queue.shift();
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
    }
    return height;
};
// @lc code=end

111. 二叉树的最小深度 - 力扣(LeetCode)

相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。
需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点

/*
 * @lc app=leetcode.cn id=111 lang=javascript
 *
 * [111] 二叉树的最小深度
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var minDepth = function(root) {
    if (root === null) return 0;
    let queue = [root];
    let depth = 0;
    while (queue.length) {
        let n = queue.length;
        depth++;
        for (let i=0; i<n; i++) {
            let node = queue.shift();
            // 如果左右节点都是null(在遇见的第一个leaf节点上),则该节点深度最小
            if (node.left === null && node.right === null) {
                return depth;
            }
            node.left && queue.push(node.left);;
            node.right && queue.push(node.right);
        }
    }
    return depth;
};
// @lc code=end

总结

二叉树的层序遍历,就是图论中的广度优先搜索在二叉树中的应用,需要借助队列来实现(此时又发现队列的一个应用了)。

扩展

在二叉树中,广度优先搜索的应用主要包括以下几个方面:

  1. 层次遍历:广度优先搜索可以实现对二叉树的层次遍历。从二叉树的根节点开始,先将根节点放入队列中,然后对队列中的节点进行出队操作,依次输出节点的值,并将其左右子节点放入队列中,直到队列为空。
  2. 查找最短路径:在二叉树中,广度优先搜索可以用于查找根节点到某个节点的最短路径。首先将根节点放入队列中,然后对队列中的节点进行出队操作,依次遍历节点的左右子节点,如果找到目标节点,则直接返回路径长度;否则,将子节点加入队列中,继续遍历,直到队列为空。
  3. 找到某一层节点:可以使用广度优先搜索来找到二叉树中的某一层节点。首先将根节点放入队列中,然后对队列中的节点进行出队操作,记录当前节点所在的层数,如果层数等于目标层,则将节点加入结果列表中;否则,将子节点加入队列中,继续遍历,直到队列为空。
  4. 判断是否为完全二叉树:广度优先搜索还可以用于判断二叉树是否为完全二叉树。首先将根节点放入队列中,然后对队列中的节点进行出队操作,依次遍历节点的左右子节点,如果当前节点只有右子节点没有左子节点,或者当前节点已经出现了只有左子节点没有右子节点的节点,则说明这不是一颗完全二叉树,直接返回false;否则,将子节点加入队列中,继续遍历,直到队列为空。如果成功遍历完所有节点,则说明这是一颗完全二叉树,返回true。

广度搜索

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/495050.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Center-based 3D Object Detection and Tracking 论文学习

论文地址&#xff1a;Center-based 3D Object Detection and Tracking Github 地址&#xff1a;Center-based 3D Object Detection and Tracking 1. 解决了什么问题&#xff1f; 在点云中&#xff0c;3D 目标通常以 3D 框的形式表示。这个表征借鉴于 2D 图像的检测&#xff0…

nvm管理node版本与node对应的npm的版本

五一长假回来打开电脑发现自己的vscode不能成功运行项目&#xff0c;npm run dev之后没有任何反应&#xff0c;于是我想着使用cmd打开试试&#xff0c;结果cmd打开后画面只有一个横着的光标再闪&#xff0c;停几秒后就自动关闭了&#xff0c;看其他的博主写的解决方法一一试过了…

错排问题之年会抽奖与抄送列表

目录 一、编程题 1.年会抽奖 2.抄送列表 二、选择题 1.操作系统中关于竞争和死锁的关系下面描述正确的是&#xff1f; 2.并发是并行的不同表述&#xff0c;其原理相同。 3.在Unix系统中&#xff0c;处于()状态的进程最容易被执行。 4.当系统发生抖动&#xff08;thrashi…

git版本升级后的问题

升级后的版本 git version 2.40.1.windows.1问题 RSA公钥和私钥是否有问题&#xff08;本地和gitlab&#xff09;[Git for Windows]的升级日志 Git for Windows 2.36.1 Git for Windows 2.33.0(2) 查看OpenSSH版本信息 OpenSSH v8.7p1 OpenSSH v8.8p1 解决方案 在本机~/.ss…

轨交展:人大金仓护航“中国式现代化的开路先锋”

2023北京-青岛国际城市轨道交通展览会 以“智赋城轨、绿色发展”为主题&#xff0c;2023北京-青岛国际城市轨道交通展览会暨高峰论坛于4月27日-29日在青岛举办&#xff0c;人大金仓携自主创新技术成果以及系列行业解决方案亮相&#xff0c;受到用户、伙伴的广泛关注和高度认可。…

GaussDB数据库基础函数介绍-下

接上一篇&#xff0c;本节继续介绍GaussDB数据库常用基础函数 目录 5、范围函数 6、窗口函数 7、聚集函数 8、安全函数 9、系统信息函数 10、动态脱敏函数 GaussDB常用基础函数介绍与示例 5、范围函数 在GaussDB数据库中&#xff0c;范围函数是指用于处理数据库范围的函…

Linux — 线程池及多线程结尾

目录 一、线程池 线程池的应用场景&#xff1a; 线程池示例&#xff1a; 二、线程安全的单例模式 什么是单例模式 什么是设计模式 单例模式的特点 饿汉实现方式和懒汉实现方式 三、STL,智能指针和线程安全 四、其他常见的各种锁 五、读者写者问题(了解) 读写锁 读写…

搭建Stable Diffusion WebUI详细过程

文章目录 1、环境搭建1.1、GPU服务器选择1.2、配置服务器环境 2、源码和模型下载3、安装依赖库文件4、运行项目5、视频教程 1、环境搭建 为了方便&#xff0c;这里直接选择Vultr提供的已安装Anaconda的Ubuntu 22.04系统。 如果你自己电脑有足够的显存&#xff0c;你也可以在自…

Nacos Config 配置帐号密码加密后,注入过程中如何解密?

背景 线上项目规定不能在配置文件中出现帐号、密码的明文信息&#xff0c;所以必须加密。 引入 Nacos Config 配置后&#xff0c;Nacos Config 帐号密码、加密&#xff0c;服务注册发现也用相同的 nacos 帐号密码&#xff0c;那么如何解密才能保证 Nacos Config 服务能够正确…

【C语言】typedef关键字

文章目录 一. 使用介绍1. 对一般类型进行重命名2. 对结构体类型进行重命名3. 对指针进行重命名4. 对数组进行重命名 二. typedef 和 #define 的区别 一. 使用介绍 typedef 的作用就是对类型进行重命名&#xff0c;具体作用在以下几个方面&#xff1a; 对一般类型进行重命名对…

IP协议的相关特性

IP协议的相关特性 &#x1f50e;地址管理动态分配NATIPv6 &#x1f50e;IP 地址的组成网络主机号的划分IP 地址分类(A, B, C, D, E)子网掩码特殊的 IP 地址 &#x1f50e;路由选择 图片来自网络 &#x1f50e;地址管理 IP地址, 本质上是一个32位的整数 通常会把32位的整数, 转…

基于ChatGLM-Med与HuaTuo的微调部署

文章目录 ChatGLM-Med推理过程微调过程 HuaTuo配置环境模型下载推理过程微调过程 如何基于领域知识对类ChatGPT模型进行微调&#xff0c;以提升类ChatGPT模型在领域的问答效果&#xff1f; 有下面两个模型&#xff0c;一起来看看微调后的效果如何。 ChatGLM-Med: 基于中文医学知…

2023亚马逊云科技研究,数字化技能为中国企业和员工带来经济效益

在中国&#xff0c;信息技术在个人、企业和宏观经济层面都推动着重大变革。为了研究这些变化所带来的影响&#xff0c;盖洛普咨询公司(Gallup)和亚马逊云科技开展了关于数字化技能的调研。 研究表明&#xff0c;数字化技能正在为中国企业和在职人员带来巨大的经济价值&#x…

【Python】贪吃蛇 —— 无聊必备的小项目

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,活动,YOLO领域博主爱笑的男孩。擅长深度学习,活动,YOLO,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typecollect个人…

【python】keras包:深度学习( RNN循环神经网络 Recurrent Neural Networks)

RNN循环神经网络 应用&#xff1a; 物体移动位置预测、股价预测、序列文本生成、语言翻译、从语句中自动识别人名、 问题总结 这类问题&#xff0c;都需要通过历史数据&#xff0c;对未来数据进行预判 序列模型 两大特点 输入&#xff08;输出&#xff09;元素具有顺序关系…

透过金瑞基金一季度运营报告,看满帮创新故事背后的长期价值

投资中国市场该投哪些行业、哪些公司&#xff1f;在投资界&#xff0c;KraneShares金瑞基金长期致力于为这个问题提供答案。中概投资者都十分熟悉的KWEB——中概互联网指数ETF&#xff0c;就来自金瑞基金。 近日&#xff0c;金瑞基金发布了2023年第一季度运营报告&#xff0c;…

入门款但配置高 极米投影仪Z6X Pro轻松打造家庭影院

近年来&#xff0c;智能投影仪凭借大屏沉浸式体验以及使用场景灵活多变的便利性深受消费者欢迎。现如今&#xff0c;智能投影仪既能替代电视的职能&#xff0c;也能灵活融入小居室、出租屋等生活场景&#xff0c;顺理成章成为年轻人的“潮品”。京东电器2022年发布的《年轻人潮…

BetaFlight统一硬件配置文件研读之dma命令

BetaFlight统一硬件配置文件研读之dma命令 1. 源由2. 代码分析2.1 cliDma2.2 showDma2.3 cliDmaopt 3. 实例分析4. 配置情况4.1 dma4.2 dma show4.3 dma device list4.4 dma pin list4.5 dma device id4.5.1 dma adc id4.5.2 dma TIMUP id4.5.3 dma pin id 4.6 dma device id s…

BI技巧丨计算组单位切换

PowerBI自带的数据显示单位有千、百万、十亿等&#xff0c;很明显这些数据单位有些时候是不太符合国人的使用习惯的。 在计算组出来之前&#xff0c;我们习惯利用配置表的方式&#xff0c;将这种数据单位转换为符合我们习惯的方式&#xff1b;在计算组出来之后&#xff0c;我们…

石油化工企业防雷工程应用解决方案

随着现代石油化工行业的不断发展&#xff0c;防雷工程的重要性也越来越凸显。在石油化工行业中&#xff0c;防雷工程是一项至关重要的工作&#xff0c;因为石油化工行业常常面临雷电等自然灾害的威胁&#xff0c;这些灾害可能导致严重的安全事故和经济损失。石化企业其生产过程…