JavaScript刷LeetCode拿offer-二叉树层序遍历篇

news2024/11/22 5:37:50

前言

博主最近在刷leetcode,做到二叉树套题的时候发现很多题的解题思路都是基于二叉树的层序遍历来完成的,因此写下这篇文章,记录一下二叉树层序遍历这件"神器"在实战的运用。

[leetcode] 102.二叉树的层序遍历

image.png

二叉树的层序遍历与传统的前序、中序、后序遍历都有一些区别,他是按层级、从左到右、从上到下进行遍历的,因此当我在遍历当前层节点的时候,肯定需要记录当前层所有节点的leftright,保存到队列中,进行下一轮遍历,直到节点没有leftright,则代表已经遍历到了最后一层了。

因此需要借助一个辅助数据结构——队列,队列先进后出,符合层序遍历的顺序性,其实此题就是队列 + 广度优先遍历 的一道结合题。

直接看代码吧:

/** * 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) {
    const res = [], queue = [];
    queue.push(root);
    if(root === null) return res;

    while(queue.length !== 0) {
        let level = [];
        const length = queue.length
        for(var i = 0; i < length; i++) {
            var node = queue.shift();
            level.push(node.val);
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
        res.push(level);
    }
    return res;
};

接下来我们逐行分析代码。

  • 首先定义了一个结果和一个队列,对应resqueue,将顶层的root节点加入到队列中,开启循环。
  • 在每一轮while 循环中,我们从左到右依次取出节点(shift api)并且判断每个节点下一层是否有后代(left、right)的判断,如果有,则加入到队列中。
  • const length = queue.length记录了队列在每一层遍历开始时的最初状态,保证了后面的for循环遍历的内容是当前层的节点,不会因为left、right加入到队列中的节点影响到当前层的循环轮数。
  • 最终,队列中所有节点都遍历完毕,在for循环中也没有发现新的下层节点,循环结束,返回结果。

此时我们就掌握了二叉树的层序遍历了,那么如下九道力扣上的题目,只需要修改模板的两三行代码(不能再多了),便可打倒!你真的会发现,理解了层序遍历后,解决这些关联题,会如鱼得水一般简单

  • 102.二叉树的层序遍历
  • 107.二叉树的层次遍历II
  • 199.二叉树的右视图
  • 637.二叉树的层平均值
  • 429.N叉树的前序遍历
  • 515.在每个树行中找最大值
  • 116.填充每个节点的下一个右侧节点指针
  • 117.填充每个节点的下一个右侧节点指针II
  • 104.二叉树的最大深度
  • 111.二叉树的最小深度

[leetcode] 107.二叉树的层序遍历II

image.png

此题与102.二叉树的层序遍历极其相似,只需要把最后的res结果的排列顺序改变一下即可,代码架构和102完全一样。

代码:

/** * 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) {
    var res = [], queue = [];
    queue.push(root);
    if(root === null) return res;
    while(queue.length) {
        let length = queue.length;
        const level = [];
        for(var i = 0; i < length; i++) {
            var node = queue.shift();
            level.push(node.val)
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
        res.unshift(level);
    }
    return res;
};

参考视频:传送门

[leetcode] 199.二叉树的右视图

image.png

此题从题目描述中可以看到,需要收集每一层的最后一个节点,有了"神器"的你,此时已经有思路了吧?这不是只需要在每一轮while循环中的for里加一个判断条件,取出最后一个节点就好了?上代码!

代码:

/** * 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) {
    var res = [], queue = [];
    queue.push(root);
    if(root === null ) return res;
    while(queue.length !== 0 ){
        const length = queue.length;
        for(var i = 0; i < length; i++) {
            var node = queue.shift();
            if(i === length - 1) {
                res.push(node.val);
            }
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
    }
    return res;
};

[leetcode] 637.二叉树的层平均值

image.png

此题只需要在每层节点取完以后,对节点的平均值进行一个计算即可,相比于前面几题,区别在收集的返回结果不一样,解题代码架构没有区别。

代码:

/** * 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 averageOfLevels = function(root) {
    var res = [], queue = [];
    queue.push(root);
    if(root === null) return res;

    while(queue.length !== 0) {
        const length = queue.length;
        let total = 0;
        for(var i = 0; i < length; i++) {
            let node = queue.shift();
            total += node.val;
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
        res.push(total / length);
    }
    return res;
};

[leetcode] 429.N叉树的层序遍历

image.png

此题会有一点小弯需要绕一下,首先数据结构不同,TreeNode节点是这样的:

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

也就是说我们在每一层节点的循环中,不是再去收集节点的leftright了,而是去遍历节点的children,将children中的节点加入到队列中。

代码:

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

/** * @param {Node|null} root
 * @return {number[][]} */
var levelOrder = function(root) {
    var res = [], queue = [];
    queue.push(root);
    if(root === null) return res;

    while(queue.length !== 0) {
        var level = [];
        var length = queue.length;
        for(var i = 0; i < length; i++) {
            var node = queue.shift();
            level.push(node.val)
            for(var item of node.children) {
                item && queue.push(item);
            }
        }
        res.push(level);
    }
    return res;
};

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

image.png

此题类似于637.二叉树的层平均值,只是每一层收集的内容变成了最大值。

代码:

/** * 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) {
    var res = [], queue = [];
    queue.push(root);
    if(root === null) return res;

    while(queue.length !== 0) {
        const length = queue.length;
        const list = [];
        for(var i = 0; i < length; i++) {
            var node = queue.shift();
            list.push(node.val);
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
        res.push(Math.max(...list));
    }
    return res;
};

[leetcode] 116. 填充每个节点的下一个右侧节点指针

image.png

此题无需重新组装新的返回内容,只需要重新组建root中的每一个节点即可,每一个TreeNode默认的nextnull,根据题目要求,在每一层所有节点,我们对除了最右节点以外的所有节点添加一个next属性即可,根据队列先进先出的原则,next的值就是queue[0],也就是队列的首项。

代码:

/** * // Definition for a Node. * function Node(val, left, right, next) { *    this.val = val === undefined ? null : val; *    this.left = left === undefined ? null : left; *    this.right = right === undefined ? null : right; *    this.next = next === undefined ? null : next; * }; */

/** * @param {Node} root
 * @return {Node} */
var connect = function(root) {
    var queue = [root];
    if(root === null) return root;
    while(queue.length) {
        const length = queue.length;
        for(var i = 0; i < length; i++) {
            var node = queue.shift();
            if(i < length - 1) {
                node.next = queue[0];
            }
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
    }
    return root;
};

[leetcode] 117. 填充每个节点的下一个右侧节点指针II

image.png

此题与116. 填充每个节点的下一个右侧节点指针 类似,直接上代码。

代码:

/** * // Definition for a Node. * function Node(val, left, right, next) { *    this.val = val === undefined ? null : val; *    this.left = left === undefined ? null : left; *    this.right = right === undefined ? null : right; *    this.next = next === undefined ? null : next; * }; */

/** * @param {Node} root
 * @return {Node} */
var connect = function(root) {
   if (root === null) {
        return null;
    }
    let queue = [root];
    while (queue.length > 0) {
        let n = queue.length;
        for (let i=0; i<n; i++) {
            let node = queue.shift();
            if (i < n-1) node.next = queue[0];
            if (node.left != null) queue.push(node.left);
            if (node.right != null) queue.push(node.right);
        }
    }
    return root;
};

[leetcode] 104. 二叉树的最大深度

image.png

此题比较简单,只需要在遍历的过程中不断记录height即可,当层序遍历结束,返回height就解决了。

/** * 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 root;
    var queue = [root];
    var height = 0;
    while(queue.length > 0) {
        const length = queue.length;
        height++;
        for(var i = 0; i < length; i++) {
            var node = queue.shift();
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
    }
    return height
};

[leetcode] 111. 二叉树的最小深度

image.png

此题与104. 二叉树的最大深度类似,区别在于需要提前结束循环,通过判断树节点是否满足node.left === null && node.right === null,就可以知道二叉树的最小深度是哪个节点,将该节点遍历时的height返回即可。

代码:

/** * 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 root;
    var queue = [root];
    var height = 0;

    while(queue.length > 0) {
        const n = queue.length;
        height++;
        for(var i = 0; i < n; i++) {
            var node = queue.shift();
            if(node.left === null && node.right === null ) {
                return height;
            }
            node.left && queue.push(node.left);
            node.right && queue.push(node.right);
        }
    }
    return height;
};

结尾

二叉树的层序遍历本质上是队列+广度优先遍历的结合运用诞生出来的"神器",此时就会发现通过它可以解决leetcode中很多二叉树的题目!

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

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

相关文章

[附源码]Python计算机毕业设计高校宿舍管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

Vue渲染器(五):快速diff算法

渲染器&#xff08;五&#xff09;&#xff1a;快速diff算法 这章开始讨论第三种用于比较新旧vnode的方式&#xff1a;快速diff算法。跟它的名字一样&#xff0c;它很快。Vue3采用的就是这种算法&#xff0c;Vue2采用的是上一章中的双端diff算法。 接下来就来着重了解它的实现…

宝塔部署前后端分离项目(Vue+SpringBoot)

目录 后端部分 配置Redis 前端部分 后端部分 1 先修改自己的speingboot配置文件&#xff0c;我的是yml文件 保证宝塔上建的数据库和自己代码里&#xff0c;就是配置文件中所建的数据库的名字是一致的密码也要保持一致&#xff0c;Redis也一样&#xff0c;如果有的话 2 记录…

关注电动汽车能效水平 提高续航能力

电动汽车&#xff08;EV&#xff09;近些年发展迅猛&#xff0c;已被汽车业内普遍认为是未来汽车发展的新方向&#xff0c;但是现如今电动汽车仍然存在一些短板&#xff0c;导致其还无法替代传统燃油车。对此&#xff0c;先想到的是电动车的续航问题。其实解决电动车续航问题主…

python 插值处理一维数据 interpolate

scipy库&#xff1a; 原码&#xff1a; https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.interp1d.html kind可选“linear”、“nearest”、“nearest-up”、“zero”、“slinear”、“quadratic”、“cubic”、“previous”或“next”之一。 “zero…

JSP sshOA办公系统myeclipse开发oracle数据库MVC模式java编程计算机网页设计

一、源码特点 JSP sshOA办公系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开 发。开发环境为TOMCAT7.0,Myecl…

音视频编解码流程与如何使用 FFMPEG 命令进行音视频处理

一、前言 FFMPEG 是特别强大的专门用于处理音视频的开源库。你既可以使用它的 API 对音视频进行处理&#xff0c;也可以使用它提供的工具&#xff0c;如 ffmpeg, ffplay, ffprobe&#xff0c;来编辑你的音视频文件。 本文将简要介绍一下 FFMPEG 库的基本目录结构及其功能&#…

OpenWrt 安装 WireGuard

下载 img镜像 https://downloads.openwrt.org/releases/22.03.2/targets/x86/generic/openwrt-22.03.2-x86-generic-generic-squashfs-combined-efi.img.gz解压 转化格式我的是Linux # 解压 gzip -d openwrt-22.03.2-x86-generic-generic-squashfs-combined-efi.img.gz #vmwa…

如何将数学曲线变为机器人轨迹-花式show爱心代码-turtlesim篇

第一步&#xff1a;找到曲线数学描述的网址。 阅读后了解曲线所对应的xy函数。 不要选太复杂的&#xff0c;毕竟先复现出来最重要的。 第二步&#xff0c;这个函数转为C代码。 //Lovegoal_x5.54.0*pow(sin(curve_t/200.0),3);goal_y5.5((13.0*cos(curve_t/200.0)-5.0*cos(curv…

网络工程师备考6章

6.1 OSI参考模型概述 计算机的整套理论是图灵提出来的,自此创办图灵奖(计算机类最高奖项)。科学远远比技术更重要。 OSI七层模型就是科学,就是理论,所以非常重要! 注:ISO是一个机构,OSI是一个协议:分别七层 6.2 OSI参考模型 注:在传输层中,什么是端到端,例如A,…

jsp+ssm计算机毕业设计ssm校园贫困补助系统【附源码】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JSPSSM mybatis Maven等等组成&#xff0c;B/S模式 Mave…

使用vite构建vue3项目与官网构建区别

使用vite构建vue3项目 一、vue3官网文档的 https://www.javascriptc.com/vue3js/guide/installation.html#命令行工具-cli npm init vite-app cd npm installnpm run dev 二、vite官网文档的 https://cn.vitejs.dev/guide/#trying-vite-online 1 对应路径cmd 输入 npm create…

Grad-CAM简介-网络 热力图分析

论文名称&#xff1a;Grad-CAM: Visual Explanations from Deep Networks via Gradient-based Localization 论文下载地址&#xff1a;https://arxiv.org/abs/1610.02391 推荐代码&#xff08;Pytorch&#xff09;&#xff1a;https://github.com/jacobgil/pytorch-grad-cam bi…

流媒体开源服务 MediaSoup 初识

目录 前言 正文 一、简单介绍 二、关键特色 1. 超强 SFU 功能 2. Node.js 模块 3. 客户端 SDK 三、架构组成 1. 关键实例 2. 重要模块 四、发展现状 前言 最近收看了一期微软&#xff08;中国&#xff09;关于云原生、大数据、AI 领域的开源服务创新的线上圆桌论坛&…

垃圾回收算法

1.种类 垃圾回收算法通常意义上有两种&#xff1a; 引用计数式垃圾收集追踪式垃圾收集 追踪式垃圾收齐又称“间接垃圾收集”&#xff0c;现在有很多算法大都遵循了分代收集理论&#xff0c;而分代收集理论的基础&#xff0c;却是以下俩个分代假说&#xff1a; 强分代假说&am…

MyPerf4J一个高性能、无侵入的Java性能监控和统计工具,有点东西!

背景 随着所在公司的发展&#xff0c;应用服务的规模不断扩大&#xff0c;原有的垂直应用架构已无法满足产品的发展&#xff0c;几十个工程师在一个项目里并行开发不同的功能&#xff0c;开发效率不断降低。 于是公司开始全面推进服务化进程&#xff0c;把团队内的大部分工程…

软件测试之移动app测试框架有哪些?

一、适用于Android的移动app测试框架 1.Espresso 十分流行的一款谷歌开发的Android测试框架&#xff0c;具备高性能性。可以创建非常简单直接的测试&#xff0c;而不必担心app的基础架构。此外&#xff0c;它是开源的&#xff0c;这使开发人员能够自定义框架。 2.Selendroid…

DOM算法系列003-获取节点A相对于节点B 的位置

UID: 20221214170009 aliases: tags: source: cssclass: created: 2022-12-14 1. 节点位置关系 两个节点A、B之间的位置关系总共有几种&#xff1f;我们第一时间能想到的&#xff1a; 节点A在节点B之后节点A在节点B之前节点A包含节点B节点A被节点B包含 除此之外&#xff0c;…

【python绘制地图——使用folium制作地图,可解决多数问题】

Python使用folium制作地图并生成png图片 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 第一章 使用folium制作地图 第二章 使用Html2Image生成png图片 第三章 使用reportlab制作pdf报告 提示&#xff1a;写完文章后&#xff0c;目录…

JavaWeb:Mysql(数据库管理系统)、Navicat(Mysql的图形化工具)

MyBatis是对JDBC的简化 以后的升级框架&#xff0c;基本都是围绕 JavaWeb程序 所做的升级 Mysql就是一个数据库管理系统&#xff0c;在系统里可以创建一个个数据库&#xff0c;即DBMS中创建一个个DB Mysqul官网https://downloads.mysql.com/archives/community/ 选择5.7.2…