二叉树的锯齿形遍历,力扣

目录

题目:

我们直接看题解吧:

快速理解解题思路小建议:

解题方法:

相似题目对比分析:

解题分析:

解题思路:

补充说明:

思路优化:

代码实现(层序遍历+倒序):


题目地址:

103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode)

难度:中等

今天刷二叉树的锯齿形遍历,大家有兴趣可以点上面链接,看看题目要求,试着做一下

题目:

二叉树的锯齿形遍历,给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

我们直接看题解吧:

快速理解解题思路小建议:

可以先简单看一下解题思路,然后照着代码看思路,会更容易理解一些。

审题目+事例+提示:

注意输出结果为二维列表

解题方法:

方法1:层序遍历+双端队列(广度优先搜索)

方法2:层序遍历+倒序

相似题目对比分析:

相似题目解题链接:->  二叉树的层序遍历,力扣-CSDN博客

此题是「102 二叉树的层序遍历」的变种,最后输出的要求有所变化,要求我们按层数的奇偶来决定每一层的输出顺序,即结果打印顺序需要交替变化。

解题分析:

规定二叉树的根节点为第 0 层,

如果当前层数是偶数,从左至右输出当前层的节点值,

否则,从右至左输出当前层的节点值。

因此,可以沿用第 102 题的思想,修改广度优先搜索,对树进行逐层遍历,用队列维护当前层的所有元素,当队列不为空的时候,求得当前队列的长度 size,每次从队列中取出 size 个元素进行拓展,然后进行下一次迭代。

为了满足题目要求的返回值为「先从左往右,再从右往左」交替输出的锯齿形,我们可以利用「双端队列」的数据结构来维护当前层节点值输出的顺序。双端队列是一个可以在队列任意一端插入元素的队列。

解题思路:

利用双端队列的两端可添加元素的特性,设打印列表(双端对列)tmp,规定:

  奇数层则添加值tmp尾部,

  偶数层则添加值tmp头部。

另外:

方法1解题,代码简短、容易实现,但需要判断每个节点的所在层奇偶性,即冗余了 N次判断。

具体流程:

1、创建队列queue与列表res

 2、BFS循环(当deque为空时跳出循环):

        a.创建新列表tmp(用于临时存储当前层的遍历结果)

        b.当前层的遍历循环(循环次数为当前层的节点数(即deque长度)):

               ·出队:队首元素出队赋值节点node

               ·打印:若为奇数层,将node.val添加至tmp尾部,反之

              ·添加子节点:若node的左()右节点非空,则加入deque

       c.将当前层结果tmp转为list并加入res.

3、返回打印结果列表res.                 

可结合理解->103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode) 

代码实现:

/**
 * 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>> zigzagLevelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        //创建双端队列,存放每层树的节点
        List<List<Integer>> res = new ArrayList<>();
       //创建二维列表,存储遍历所得节点值
        if (root != null) queue.add(root);  
         //若根节点非空,则将根节点添加至queue队列
        while (!queue.isEmpty()) {//BFS循环,当deque为空时跳出循环
            LinkedList<Integer> tmp = new LinkedList<>();
            //创建新列表tmp(用于临时存储当前层的遍历结果)
            for(int i = queue.size(); i > 0; i--) {
            //循环次数为当前层的节点数(即deque长度)
                TreeNode node = queue.poll();//队首元素出队赋值节点node
                if (res.size() % 2 == 0) tmp.addLast(node.val);
               //若为奇数层,将node.val添加至tmp尾部,反之
                else tmp.addFirst(node.val);
                if (node.left != null) queue.add(node.left);
               //若node的左节点非空,则加入deque
                if (node.right != null) queue.add(node.right);
               //若node的右节点非空,则加入deque
            }
            res.add(tmp);//将当前层遍历结果添加到res
        }
        return res;
    }
}

补充说明:

1、特殊处理:当树的根节点为空,则直接返回空列表[]

2、 打印结果空列表 res ,包含根节点的双端队列 deque,相当于初始化操作 。

3、本题解题代码将链表 LinkedList 作为双端队列使用

4、注意:这个是伪锯齿形遍历,相当于只是结果字符串反转了而已,遍历都是从左往右遍历,只不过在组装结果的时候改变了顺序,而没有按照先从左往右,再从右往左进行下一层遍历。

 

思路优化:

由方法1解题可知该方法需要判断每个节点的所在层奇偶性,即冗余了 N次判断,

因此通过将奇偶层逻辑拆分,可以消除冗余的判断,进一步优化解题方法。

主要优化在 BFS 循环部分。

算法流程:

   BFS 循环: 循环打印奇 / 偶数层,当 deque 为空时跳出。
   打印奇数层: 从左向右打印,先左后右 加入下层节点。
  若 deque 为空,说明向下无偶数层,则跳出。
  打印偶数层: 从右向左 打印,先右后左 加入下层节点。

     while (!deque.isEmpty()) {
            // 打印奇数层
            List<Integer> tmp = new ArrayList<>();
            for(int i = deque.size(); i > 0; i--) {
                // 从左向右打印
                TreeNode node = deque.removeFirst();
                tmp.add(node.val);
                // 先左后右加入下层节点
                if (node.left != null) deque.addLast(node.left);
                if (node.right != null) deque.addLast(node.right);
            }
            res.add(tmp);
            if (deque.isEmpty()) break; // 若为空则提前跳出
            // 打印偶数层
            tmp = new ArrayList<>();
            for(int i = deque.size(); i > 0; i--) {
                // 从右向左打印
                TreeNode node = deque.removeLast();
                tmp.add(node.val);
                // 先右后左加入下层节点
                if (node.right != null) deque.addFirst(node.right);
                if (node.left != null) deque.addFirst(node.left);
            }
            res.add(tmp);
        }

 

代码实现(层序遍历+倒序):

  • 此方法的优点是只用列表即可,无需其他数据结构。
  • 偶数层倒序: 若 res 的长度为 奇数 ,说明当前是偶数层,则对 tmp 执行 倒序 操作。
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
        if (root != null) queue.add(root);
        while (!queue.isEmpty()) {
            List<Integer> tmp = new ArrayList<>();
            for(int i = queue.size(); i > 0; i--) {
                TreeNode node = queue.poll();
                tmp.add(node.val);//直接添加节点
                if (node.left != null) queue.add(node.left);//添加子节点
                if (node.right != null) queue.add(node.right);
            }
         //偶数层倒序:若res的长度为奇数,说明当前是偶数层,则对tmp执行倒序操作。
            if (res.size() % 2 == 1) Collections.reverse(tmp);
            res.add(tmp);
        }
        return res;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

osg模型的平移、缩放、旋转

加载2个模型&#xff0c;其中一个向上移动28个单位&#xff1b; 加载2个模型&#xff0c;其中一个缩放0.5倍&#xff0c;向下移动22个单位&#xff1b; 加载2个模型&#xff0c;其中一个缩放0.5倍、旋转45度、向右向下移动几个单位&#xff1b; 都是用矩阵实现的&#xff1b; …

基于CEVA DSP BX2的架构分析(六)-加载和存储单元(二)

6.4 指针修改机制 LS0和LS1都包含指针修改机制。当使用间接或索引寻址模式时&#xff0c;指针的修改可以与地址生成并行执行。在间接寻址模式中&#xff0c;指针包含地址&#xff0c;而在变址寻址模式下&#xff0c;指针包含偏移量&#xff08;有关这些寻址模式的更多详细信息&…

axios get 请求 url 转码 空格转成+,导致请求失败(前端解决)

问题 GET 请求参数&#xff1a; URL-encoded 后&#xff1a; 浏览器将空格转成了&#xff0c;导致服务报错&#xff0c;返回 400。 解决 在请求拦截器中&#xff0c;对 params 进行处理。 axios.interceptors.request.use((config) > {let url config.url;if (config…

收藏:相当大赞的来自 Agilean产品团队的2篇关于重塑敏捷组织的绩效管理的文章

Agilean产品团队&#xff0c;是吴穹博士领导下最近在国内敏捷界很厉害的产品&#xff0c;今天看到两篇相当不错的说敏捷组织的上下篇文章&#xff0c;分享下&#xff0c;地址是&#xff1a;6个原则15项举措&#xff0c;重塑敏捷组织的绩效管理&#xff08;上&#xff09; 6个原…

Unity接入GVoice腾讯实时语音

Unity接入GVoice腾讯实时语音 一、介绍二、注册GVoice创建项目语音服务1.创建项目2.申请语音权限3.项目管理查看SDK初始化的一些参数和基本信息4.GVoice检测 三、SDK下载SDK是分为两种类型&#xff1a;独立版集成板 SDK放入Unity工程中 四、语音代码写法五、GVoice踩坑语音权限…

C#委托的前世今生

起因 很多C#初学者&#xff0c;都遇到过这样的问题——线程间操作无效&#xff0c;从不是创建控件的线程访问它。 今天就这个问题&#xff0c;展开分析。 溯源 先说下这个问题产生的根源。 大家都知道&#xff0c;程序运行起来之后&#xff0c;首先会有一个主线程&#xff…

CTF-show WEB入门--web19

今晚web19也就顺便解决了 老样子我们先打开题目看看题目提示&#xff1a; 可以看到题目提示为&#xff1a; 密钥什么的&#xff0c;就不要放在前端了 然后我们打开题目链接&#xff1a; 然后我们查看网页源代码&#xff1a; 可以发现有用的内容全在网页源代码里。 前端验证…

将markdown格式内容在界面中展示出来(搭配上一篇使用)

1.定义一个div content 是你向展示的 markdown 格式数据 <div id"previewMarkdown"><textarea>{{ content }}</textarea> </div>2.导入js 这个都是 lib 目录下的 js 文件&#xff0c;因为 markdown 组件依赖这些 js 文件 <script src…

红外避障模块

目录 一、模块原理 二、模块使用说明 三、材料准备 四、代码 五、实验效果 实验效果 自动灯效果&#xff1a; 避障模块-CSDN直播 一、模块原理 红外避障模块利用光反射原理&#xff0c;模块前端拥有一个红外发射管和一个红外接收管。模块通电后红外发射管向前方不断发射…

vue前端RSA使用公钥进行加密,公钥进行解密

记录下RSA使用公钥进行加密&#xff0c;公钥进行解密&#xff1a; 背景&#xff1a;由于项目要求前后端进行数据加密传输&#xff0c;具体数据使用aes进行加密&#xff0c;aes密钥使用rsa进行加密&#xff0c;加密后的aes密钥放在请求头和响应头进行传输。这里实现的是前端vue…

springboot159基于springboot框架开发的景区民宿预约系统的设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

net start mysql服务名无效|发生系统错误 解决办法

未输入正确的mysql服务名 解决办法&#xff1a; 使用net start命令查看可用的服务名&#xff0c;找到mysql的服务名 未使用管理员身份运行命令提示符 解决方法&#xff1a; 使用管理员身份运行命令提示符

十分钟GIS——geoserver+postgis+udig从零开始发布地图服务

1数据库部署 1.1PostgreSql安装 下载到安装文件后&#xff08;postgresql-9.2.19-1-windows-x64.exe&#xff09;&#xff0c;双击安装。 指定安装目录&#xff0c;如下图所示 指定数据库文件存放目录位置&#xff0c;如下图所示 指定数据库访问管理员密码&#xff0c;如下图所…

opensuse安装百度Linux输入法

前言 Linux下有输入法&#xff0c;拼音&#xff0c;百度的都有&#xff0c;但是用起来总感觉不如在windows下与安卓中顺手。 目前搜狗与百度都出了Linux的输入法&#xff0c;但是没有针对OpenSUSE的&#xff0c;只有ubuntu/deepin/UOS的安装包。 本文主要讲的如何把百度Linux输…

2024.2.6日总结(小程序开发3)

页面配置 页面配置和全局配置的关系&#xff1a; 小程序中&#xff0c;app.json中的window节点&#xff0c;可以全局配置小程序中每个页面的窗口表现 如果某些小程序想要有特殊的窗口表现&#xff0c;可以用页面级别的.json配置文件实现这个需求 页面配置和全局配置冲突时&…

嵌入式软件bug分析基本要求

摘要&#xff1a;软件从来不是一次就能完美的&#xff0c;需要以包容的眼光看待它的残缺。那问题究竟为何产生&#xff0c;如何去除呢&#xff1f; 1、软件问题从哪来 软件缺陷问题千千万万&#xff0c;主要是需求、实现、和运行环境三方面。 1.1 需求描述偏差 客户角度的描…

手撕spring bean的加载过程

这里我们采用手撕源码的方式&#xff0c;开始探索spring boot源码中最有意思的部分-bean的生命周期&#xff0c;也可以通过其中的原理理解很多面试以及工作中偶发遇到的问题。 springboot基于约定大于配置的思想对spring进行优化&#xff0c;使得这个框架变得更加轻量化&#…

Redis-布隆过滤器解决穿透详解

本文已收录于专栏 《中间件合集》 目录 背景介绍概念说明原理说明解决穿透安装使用安装过程Redis为普通安装的配置方式Redis为Docker镜像安装的配置方式 具体使用控制台操作命令说明Spring Boot集成布隆过滤器 总结提升 背景介绍 布隆过滤器可以帮助我们解决Redis缓存雪崩的问题…

【JS逆向学习】今日头条

逆向目标 目标网页&#xff1a;https://www.toutiao.com/?wid1707099375036目标接口&#xff1a;https://www.toutiao.com/api/pc/list/feed目标参数&#xff1a;_signature 逆向过程 老规矩先观察网络请求&#xff0c;过滤XHR请求观察加密参数&#xff0c;发现Payload的_s…