LeetCode-102.题: 二叉树的层序遍历(原创)

news2024/12/23 12:19:59

【题目描述】

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

示例 1:

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

【题目链接】. - 力扣(LeetCode)

【解题代码】

package tree.binarytree;

import java.util.*;

public class LevelOrderTraversal {
    public static void main(String[] args) {
        Integer[] array = new Integer[]{1,2,3,4,null,null,5};
        TreeNode root = TreeNode.constructTree(array);
        List<List<Integer>> lists = new LevelOrderTraversal().levelOrder(root);
        lists.forEach(l -> System.out.println(Arrays.toString(l.toArray())));
    }

    private List<List<Integer>> levelOrder(TreeNode root) {
        // 特殊情况处理,如果树根节点为空,返回空列表
        if (root == null) return new ArrayList<>();

        // 定义一个队列,临时存放所访问的树节点
        Queue<TreeNode> queue = new LinkedList<>();
        // 首先将树的根节点放入队列中
        queue.add(root);
        TreeNode node;
        // 存储所有层节点列表的列表
        List<List<Integer>> lists = new ArrayList<>();
        // 初始化当前父节点个数为1(即根节点),以及子节点个数
        int curLevelCount = 1, nextLevelCount = 0;
        // 当前层节点列表
        List<Integer> list = new ArrayList<>();
        while (curLevelCount > 0) {
            // 从队列里弹出一个父节点,并将父节点数据减1
            node = queue.poll();
            curLevelCount--;
            // 将此父节点放入当前层节点列表
            list.add(node.val);
            // 如果此节点左子节点不为空,放入队列中,并将子节点数目加1
            if (node.left != null) {
                queue.add(node.left);
                nextLevelCount++;
            }
            // 如果此节点右子节点不为空,放入队列中,并将子节点数目加1
            if (node.right != null) {
                queue.add(node.right);
                nextLevelCount++;
            }
            // 如果当前层父节点访问完毕
            if (curLevelCount == 0){
                // 将当前层节点,拷贝到结果列表中,并进行清空
                lists.add(new ArrayList<>(list));
                list.clear();
                // 然后将下一层所有节点作为当前层节点,重启新一轮的遍历
                curLevelCount = nextLevelCount;
                nextLevelCount = 0;
            }
        }
        // 最后返回结果
        return lists;
    }
}

【解题思路】

        我们之前数据结构学习树遍历的内容,一般都是左、中、右三种遍历循序,按树的层次遍历还没处理过,需要自行思考,不能借鉴教科书了,深入反复思考,得出以下几个要点

  1. 第一层就一个节点,树的根节点,第二层就是根节点的左右子节点,第三层就是根节点的左右子节点的所有左右子节点,后面以此类推。。。
  2. 每次我们可以在队列中保存当前层的树节点,然后一一弹出,放入当前层列表中,并将其子节点放入队列中
  3. 当前层访问结束后,剩下的就是当前层的下一层所有节点。将其设置为新的当前层,反复循环处理即可

按照这个思路,很快就写出算法代码,并提交成功,解题步骤如下:

【解题步骤】

  1. 定义当前层树节点列表以及结果所有层节点列表
    // 定义一个队列,临时存放所访问的树节点
    Queue<TreeNode> queue = new LinkedList<>();
    // 存储所有层节点列表的列表
    List<List<Integer>> lists = new ArrayList<>();
  2. 定义一个队列,临时存放所访问的树节点,首先将树的根节点放入队列中
    // 定义一个队列,临时存放所访问的树节点
    Queue<TreeNode> queue = new LinkedList<>();
    // 存储所有层节点列表的列表
    queue.add(root);
  3. 初始化当前父节点个数为1(即根节点),以及子节点个数
    int curLevelCount = 1, nextLevelCount = 0;
  4. 依次遍历当前层所有节点,一一从队列里弹出,放入当前层节点列表
    while (curLevelCount > 0) {
        // 从队列里弹出一个父节点,并将父节点数据减1
        node = queue.poll();
        curLevelCount--;
        // 将此父节点放入当前层节点列表
        list.add(node.val);
  5. 将其左右子节点作为下一层节点加入队列中
    // 如果此节点左子节点不为空,放入队列中,并将子节点数目加1
    if (node.left != null) {
        queue.add(node.left);
        nextLevelCount++;
    }
    // 如果此节点右子节点不为空,放入队列中,并将子节点数目加1
    if (node.right != null) {
        queue.add(node.right);
        nextLevelCount++;
    }
  6. 如果当前层所有节点遍历完毕,将当前层节点,拷贝到结果列表中,并进行清空,然后将下一层所有节点作为当前层节点,重启新一轮的遍历
    ​
    // 如果当前层父节点访问完毕
    if (curLevelCount == 0){
        // 将当前层节点,拷贝到结果列表中,并进行清空
        lists.add(new ArrayList<>(list));
        list.clear();
        // 然后将下一层所有节点作为当前层节点,重启新一轮的遍历
        curLevelCount = nextLevelCount;
        nextLevelCount = 0;
    }
    
    ​
  7. 最后返回结果
    return lists;

【思考总结】

  1. 这道理的关键点在于“自顶向下,一层接一层交替访问树节点”;
  2. 算法设计时,可以考虑最简单的情况,试探思考其运行逻辑应该是什么样的
  3. 还是要有精细化的逻辑思维,层次分明,这样在复杂的逻辑也不会乱;
  4. LeetCode解题之前,可以看提示,但一定不要看题解,看了就“破功”了!

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

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

相关文章

Linux进程概念僵尸进程孤儿进程

文章目录 一、什么是进程二、进程的状态三、Linux是如何做的&#xff1f;3.1 R状态3.2 S状态3.3 D状态3.4 T状态3.5 t状态3.6 X状态3.7 Z状态 四、僵尸进程4.1 僵尸进程危害 五、孤儿进程 一、什么是进程 对于进程理解来说&#xff0c;在Windows上是也可以观察到的&#xff0c…

数据结构与算法第三套试卷小题

1.删除链表节点 **分析&#xff1a;**首先用指针变量q指向结点A的后继结点B&#xff0c;然后将结点B的值复制到结点A中&#xff0c;最后删除结点B。 2.时间复杂度的计算 **分析&#xff1a;**当涉及嵌套循环的时候&#xff0c;我们可以直接分析内层循环即可&#xff0c;看内…

sql注入基础学习

1.常用SQL语句 01、显示数据库 show databases&#xff1b; 02、打开数据库 use db name&#xff1b; 03、显示数据表 show tables&#xff1b; 04、显示表结构 describe table_name&#xff1b; 05、显示表中各字段信息&#xff0c;即表结构 show columns from table_nam…

【框架学习 | 第五篇】SpringMVC(常用注解、获取请求参数、域对象共享数据、拦截器、异常处理、上传/下载文件)

文章目录 1.SpringMVC简介1.1定义1.2主要组件1.3工作流程1.3.1简要流程1.3.2详细流程 1.4优缺点 2.常用注解3.获取请求参数3.1通过 HttpServletRequest 获取请求参数3.2通过控制器方法的形参获取请求参数3.2.1请求路径参数与方法形参一致3.2.2请求路径参数与方法形参不一致3.2.…

笔记本电脑使用时需要一直插电吗?笔记本正确的充电方式

随着科技的不断发展&#xff0c;笔记本电脑已经成为人们日常生活和工作中不可或缺的电子设备。而在使用笔记本电脑时&#xff0c;很多人会有一个疑问&#xff0c;那就是笔记本电脑使用时需要一直插电吗&#xff1f;本文将就此问题展开讨论。 不一定需要一直插电&#xff0c;如果…

C++:2024/3/11

作业1&#xff1a;编程 要求&#xff1a;提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数 代码&#xff1a; #include <iostream>using namespace std;int main() {string str;cout << "请输入一个字…

sql-mysql可视化工具Workbench导入sql文件

mysql可视化工具Workbench导入sql文件 1、打开workbench2、导入sql文件3、第一行加上库名4、开始运行 1、打开workbench 2、导入sql文件 3、第一行加上库名 4、开始运行

参与Penpad launch任务,实现Penpad与Scroll的双空投

在比特币 ETF 、BTC 减半等利好消息的持续推动下&#xff0c;加密市场逐渐进入到新一轮牛市周期中。除了以太坊 Layer1 生态 TVL 不断飙升外&#xff0c;Layer2 赛道 TVL 也在不断飙升并且屡创新高。 而在牛市背景下&#xff0c;Layer2 空投所带来的财富效应预期正在被进一步拉…

IAB视频广告标准《数字视频和有线电视广告格式指南》之 目录和概述及视频配套广告 - 我为什么要翻译介绍美国人工智能科技公司IAB系列(2)

写在前面 谈及到中国企业走入国际市场&#xff0c;拓展海外营销渠道的时候&#xff0c;如果单纯依靠一个小公司去国外做广告&#xff0c;拉渠道&#xff0c;找代理公司&#xff0c;从售前到售后&#xff0c;都是非常不现实的。我们可以回想一下40年前&#xff0c;30年前&#x…

Facebook商城号为什么被封?如何防封?

由于Facebook商城的高利润空间&#xff0c;越来越多的跨境电商商家注意到它的存在。Facebook作为全球最大、用户量最大的社媒平台&#xff0c;同时也孕育了一个巨大的商业生态&#xff0c;包括广告投放、商城交易等。依托背后的大流量&#xff0c;Facebook商城起号较快&#xf…

接口测试\接口测试脚本之Jsoup解析HTML

第一次接触jsoup还是在处理收货地址的时候&#xff0c;当时在写一个下单流程&#xff0c;需要省市区id以及详细门牌号等等&#xff0c;因此同事介绍了jsoup,闲来无事&#xff0c;在此闲扯一番&#xff01; 1.我们来看下&#xff0c;什么是jsoup,先来看看官方文档是怎么说的&am…

【深度学习】换脸新科技,InstantID: Zero-shot Identity-Preserving Generation in Seconds

论文&#xff1a;https://arxiv.org/abs/2401.07519 代码:https://github.com/InstantID/InstantID demo&#xff1a;https://huggingface.co/spaces/InstantX/InstantID 文章目录 1 引言2 相关工作2.1 文本到图像扩散模型2.2 主题驱动的图像生成2.3 保持ID的图像生成 3 方法3.…

深入理解Vue.js中的nextTick:实现异步更新的奥秘

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【wps】wps与office办公函数储备使用(结合了使用案例 持续更新)

【wps】wps与office办公函数储备使用(结合了使用案例 持续更新) 1、TODAY函数 返回当前电脑系统显示的日期 TODAY函数&#xff1a;表示返回当前电脑系统显示的日期。 公式用法&#xff1a;TODAY() 2、NOW函数 返回当前电脑系统显示的日期和时间 NOW函数&#xff1a;表示返…

群晖NAS使用Docker安装WPS Office并结合内网穿透实现公网远程办公

文章目录 推荐1. 拉取WPS Office镜像2. 运行WPS Office镜像容器3. 本地访问WPS Office4. 群晖安装Cpolar5. 配置WPS Office远程地址6. 远程访问WPS Office小结 7. 固定公网地址 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff…

美国国家安全局(NSA)和美国政府将Delphi/Object Pascal列为推荐政府机构和企业使用的内存安全编程语言

上周&#xff0c;美国政府发布了《回到构建块&#xff1a;通往安全和可衡量软件的道路》的报告。本报告是美国网络安全战略的一部分&#xff0c;重点关注多个领域&#xff0c;包括内存安全漏洞和质量指标。 许多在线杂志都对这份报告发表了评论&#xff0c;这些杂志强调了对 C…

OpenCV学习笔记(五)——图片的缩放、旋转、平移、裁剪以及翻转操作

目录 图像的缩放 图像的平移 图像的旋转 图像的裁剪 图像的翻转 图像的缩放 OpenCV中使用cv2.resize()函数进行缩放&#xff0c;格式为&#xff1a; resize_imagecv2.resize(image,(new_w,new_h),插值选项) 其中image代表的是需要缩放的对象&#xff0c;(new_w,new_h)表…

Python元组(Tuple)深度解析!

目录 1. 什么是元组&#xff1f; 2. 创建元组 3.访问元组 4.元组的运算 5.修改元组不可行 6.元组的应用场景 前面的博客里&#xff0c;我们详细介绍了列表&#xff08;List&#xff09;这一种数据类型&#xff0c;现在我们来讲讲与列表相似的一种数据类型&#xff0c;元组…

portapack-h2使能hackrf

这两天弄了一块portapack扩展板 &#xff0c;可以用来脱机使能hackrf,简单的说&#xff0c;这是一块自带屏幕&#xff0c;预装gnuradio环境的单片机&#xff0c;通过GPIO插入hackrf,可以使能hackrf&#xff0c;脱机运行一些无线电测试程序。 购置的拓展先不用着急装扩展板&…

Web3 之路:构建开放、透明的数字生态系统

随着区块链技术的迅速发展&#xff0c;Web3正在成为数字世界的新引擎&#xff0c;重新定义着我们的生活和工作方式。在这个数字化的时代&#xff0c;我们目睹着一个全新的网络生态正在逐渐成形&#xff0c;其中开放性和透明性是其核心特征。让我们深入探讨&#xff0c;Web3如何…