剑指offer JZ77 按之字形顺序打印二叉树

Java JZ77 按之字形顺序打印二叉树


文章目录

  • Java JZ77 按之字形顺序打印二叉树
  • 一、题目描述
  • 二、双栈法
  • 三、队列+reverse()法


   使用双栈法和队列+reverse()法解决剑指offer JZ77 按之字形顺序打印二叉树的问题。


一、题目描述

  给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替)

  数据范围:0≤n≤1500,树上每个节点的val满足 ∣val∣<=1500。
  要求:空间复杂度:O(n),时间复杂度:O(n)。
  例如:给定的二叉树是{1,2,3,#,#,4,5}
在这里插入图片描述
  该二叉树之字形层序遍历的结果是
  [
  [1],
  [3,2],
  [4,5]
  ]

  示例1

输入:{1,2,3,#,#,4,5}
返回值:[[1],[3,2],[4,5]]

  说明:如题面解释,第一层是根节点,从左到右打印结果,第二层从右到左,第三层从左到右。

  示例2

输入:{8,6,10,5,7,9,11}
返回值:[[8],[10,6],[5,7,9,11]]

  示例3

输入:{1,2,3,4,5}
返回值:[[1],[3,2],[4,5]]

二、双栈法

  知识点:栈

  栈是一种仅支持在表尾进行插入和删除操作的线性表,这一端被称为栈顶,另一端被称为栈底。元素入栈指的是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;元素出栈指的是从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
  我们可以利用两个栈遍历这棵二叉树,第一个栈L_R从根节点开始记录第一层,然后依次遍历两个栈,遍历第一个栈时遇到的子节点依次加入第二个栈R_L中,即是第二层。
  而遍历第二个栈R_L的时候因为是先进后出,因此就是逆序的,再将第二个栈R_L的子节点依次加入第一个栈L_R中。于是原本的逆序在第一个栈L_R中又变回了正序,如果反复交替直到两个栈都空为止。

public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
//一个二维的ArrayList,其中每个元素都是一个ArrayList类型的对象。
        ArrayList<ArrayList<Integer> > listAll = new ArrayList<>();
//如果是空,则直接返回空
        if (pRoot == null) {
            return listAll;
        }
        Stack<TreeNode> L_R = new Stack<TreeNode>();   //第一个栈,存放奇数行,从左打印的行
        Stack<TreeNode> R_L = new Stack<TreeNode>();	 //第一个栈,存放偶数行,从右打印的行
        int level = 1;		//记录数层
        L_R.push(pRoot);	//放入根节点
 //循环遍历,直到某个奇数行或者偶数行为空
        while (!L_R.isEmpty() || !R_L.isEmpty()) {
            ArrayList<Integer> list = new ArrayList<>();	//二维矩阵中的行对象,用来短暂保存每层节点数
 //level++ % 2,level先取余后加,判断是否为奇数行
            if (level++ % 2 != 0) {		
                while (!L_R.isEmpty()) {		
                    TreeNode node = L_R.pop();	//先将奇数层的节点保存进list
                    list.add(node.val);
//下一层是偶数层是从右打印,栈先进后出,所以先保存左子节点
                    if (node.left != null) {
                        R_L.push(node.left);
                    }
                    if (node.right != null) {	//再保存右子节点
                        R_L.push(node.right);
                    }
                }
            } else {   //如果是偶数行
                while (!R_L.isEmpty()) {
                    TreeNode node = R_L.pop();	//先将偶数层的节点保存进list
                    list.add(node.val);
                    System.out.println(node.val);
//下一层是奇数层是从左打印,栈先进后出,所以先保存右子节点,再保存左子节点
                    if (node.right != null){
                        L_R.push(node.right);
                    }
                    if (node.left != null){
                        L_R.push(node.left);
                    }
                }
            }
            listAll.add(list);		//每层节点遍历后,将保存该层节点的list整体加入到 二维listAll中
        }
        return listAll;		//遍历结束返回二维listAll
    }

}

三、队列+reverse()法

  知识点:队列

  队列是一种仅支持在表尾进行插入操作、在表头进行删除操作的线性表,插入端称为队尾,删除端称为队首,因整体类似排队的队伍而得名。它满足先进先出的性质,元素入队即将新元素加在队列的尾,元素出队即将队首元素取出,它后一个作为新的队首。
reverse()函数
  在Java中,Collections是一个工具类,提供了一系列静态方法,用于操作集合类。其中,reverse()函数是Collections类中的一个静态方法,用于对List类型的集合进行反转操作。该函数的定义如下:

public static void reverse(List<?> list)

  其中,list表示要进行反转操作的List集合。该函数会将List集合中的元素按照相反的顺序重新排列。需要注意的是,该函数会直接修改原始的List集合,而不是返回一个新的List集合。

  解题思路:

  按照层次遍历按层打印二叉树的方式,每层分开打印,然后对于每一层利用flag标记,第一层为false,之后每到一层取反一次,如果该层的flag为true,则记录的数组整个反转即可。

  但是难点在于如何每层分开存储,从哪里知晓分开的时机?
  在层次遍历的时候,我们通常会借助队列(queue)。当根节点进入队列时,队列长度为1,第一层节点数也为1;若是根节点有两个子节点,push进队列后,队列长度为2,第二层节点数也为2;若是根节点一个子节点,push进队列后,队列长度为为1,第二层节点数也为1。由此,我们可知,每层的节点数等于进入该层时队列长度,因为刚进入该层时,这一层每个节点都会push进队列,而上一层的节点都出去了。

  具体做法:
 ● step 1:首先判断二叉树是否为空,空树没有打印结果。
 ● step 2:建立辅助队列,根节点首先进入队列。不管层次怎么访问,根节点一定是第一个,那它肯定排在队伍的最前面,初始化flag变量。
 ● step 3:每次进入一层,统计队列中元素的个数,更改flag变量的值。因为每当访问完一层,下一层作为这一层的子节点,一定都加入队列,而再下一层还没有加入,因此此时队列中的元素个数就是这一层的元素个数。
 ● step 4:每次遍历这一层这么多的节点数,将其依次从队列中弹出,然后加入这一行的一维数组中,如果它们有子节点,依次加入队列排队等待访问。
step 5:访问完这一层的元素后,根据flag变量决定将这个一维数组直接加入二维数组中还是反转后再加入,然后再访问下一层。(奇数行反转,偶数行不反转)。

import java.util.*;
public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        TreeNode head = pRoot;
        ArrayList<ArrayList<Integer> > res = new ArrayList<ArrayList<Integer>>();
        if(head == null)
            //如果是空,则直接返回空list
            return res;
        //队列存储,进行层次遍历
        Queue<TreeNode> temp = new LinkedList<TreeNode>();
        temp.offer(head);
        TreeNode p;
        boolean flag = true;
        while(!temp.isEmpty()){
            //记录二叉树的某一行
            ArrayList<Integer> row = new ArrayList<Integer>(); 
            int n = temp.size();
            //奇数行反转,偶数行不反转
            flag = !flag;
            //因先进入的是根节点,故每层节点多少,队列大小就是多少
            for(int i = 0; i < n; i++){
                p = temp.poll();
                row.add(p.val);
                //若是左右孩子存在,则存入左右孩子作为下一个层次
                if(p.left != null)
                    temp.offer(p.left);
                if(p.right != null)
                    temp.offer(p.right);
            }
            //奇数行反转,偶数行不反转
            if(flag) 
                Collections.reverse(row);
            res.add(row);
        }
        return res;
    }
}

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

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

相关文章

【pytorch】深度学习模型调参策略(五):采用贝叶斯工具进行最优参数搜索及最佳步数确认

目录1.如何决定是否应用某个新的超参数配置2.参数优化工具optuna确定最终最优配置为什么在调整的探索阶段使用准随机搜索而不是更复杂的黑盒优化算法&#xff1f;optuna库简介pytorch实现代码搜索参数详解输出结果3.确定每次训练运行的步数使用学习率扫描选择max_train_steps初…

设置鼠标右键打开方式,添加IDEA的打开方式

一、问题描述 已下载IDEA&#xff0c;但是右键打开之前保存的项目文件&#xff0c;无法显示以IDEA方式打开。 二、解决步骤 1. 打开注册表 winR键输入regedit 2、查找路径为计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell &#xff08;我找了半天没看到Class…

在芯片设计行业,从项目的初期到交付,不同的岗位的工程师主要负责什么?

大家都知道在芯片设计行业&#xff0c;项目是至关重要的一环。从项目的初期到交付&#xff0c;不同的岗位的工程师在项目的各环节主要负责什么?他们是怎样配合的?下面看看资深工程师怎么说。 一个项目&#xff0c;从初期到交付的过程是比较漫长的。我们知道最早的时候&#…

deskvideosys 办公行为管理软件的部署架构

deskvideosys 办公行为管理软件服务器端使用的是 B/S 架构&#xff0c;采用 golangvue 框架来编程&#xff0c;agent 端直接使用的是 vc编程框架&#xff0c;然后通过tcp协议连接服务器端&#xff0c;所以deskvideosys架构 可以作为终端安全管理&#xff0c;上网行为管理&#…

小程序 table组件

最近有在小程序中用table的需求&#xff0c;但是没有找到有符合要求的组件&#xff0c;所以自己弄了一个&#xff0c;能满足基本需求。 组件下载:https://download.csdn.net/download/weixin_67585820/85047405 引入 "usingComponents": {"table": "…

基于springboot和Web实现社区医院管理服务系统【源码+论文】分享

基于springboot和Web的社区医院管理服务系统演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Mave…

记录--Vue 3 中的极致防抖/节流(含常见方式防抖/节流)

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 今天给大家带来的是Vue 3 中的极致防抖/节流(含常见方式防抖/节流)这篇文章&#xff0c;文章中不仅会讲述原来使用的防抖或节流方式&#xff0c;还会带来新的一种封装方式&#xff0c;使用起来更简单、…

diffusion 之 cifar/mnist 数据集

diffusion 之 mnist 数据集mnist数据集ddpm/script_utils.pyscripts/train_mnist.py展示采样结果代码出处&#xff1a;https://github.com/abarankab/DDPMwandb的问题解决方法&#xff1a; step1&#xff1a; 按照这个https://blog.csdn.net/weixin_43164054/article/details/1…

基于kubernetes部署gitlab

目录前提下载镜像部署服务前提 已经搭建完kubernets集群并可提供服务。 下载镜像 去docker hub 下载具体版本镜像&#xff0c;当使用最新版本时&#xff0c;也建议具体制定版本号&#xff0c;而不是使用latest. 如 gitlab/gitlab-ce:15.10.0-ce.0 当然可以pull到本地&#x…

Linux拒绝俄罗斯开发者合入

最近在Linux社区看到这样的信息https://lore.kernel.org/all/20230314103316.313e5f61kernel.org/我们不愿意接受你们的补丁。关于上面的内容&#xff0c;看到有一篇这样的文章https://www.phoronix.com/news/Linux-STMAC-Russian-Sanctions由于美国对俄罗斯实施制裁&#xff0…

一次内存泄露排查

前因&#xff1a; 因为测试 长时间压测导致 接口反应越来越慢&#xff0c;甚至 导致服务器 崩溃 排查过程 1、top 查看是 哪个进程 占用 内存过高 2、根据 进程 id 去查找 具体是哪个 程序的问题 ps -ef| grep 41356 可以看到 具体的 容器位置 排查该进程 对象存活 状态…

大数据学习路线图(2023完整高清版超详细)

送福利了&#xff01;超详细的大数据学习路线图来啦&#xff0c;2023版是首发哟&#xff01;大数据学习路线图分为7个阶段&#xff0c;包含&#xff1a; 数据仓库基础-->Linux &Hadoop生态-->Hadoop-->数据仓库与ETL技术-->BI数据分析与可视化-->自研数据仓…

计算机科学与技术专业-大三-学年设计-题目

大三-学年设计题目 西南大学 计算机与信息科学学院 周竹荣 课程概述 学年设计是重要的综合性设计训练&#xff0c;安排在修完相关专业平台课后进行。旨在培养学生综合运用所学的基础理论和专业知识&#xff0c;分析、解决实际问题的能力&#xff0c;理论联系实际。是一次系统的…

HTML 标签和属性

一些标签 单双标签 双标签。双标签指标签是成对出现的&#xff0c;也就是有一个开始标签和一个结束标签&#xff0c;开始标签用 <标签名> 表示&#xff0c;结束标签用 </标签名> 表示&#xff0c;只有一对标签一起使用才能表示一个具体的含义。例如 <html>&…

关于线程池你了解些什么?

前言学习线程池的思维导图线程池是什么?它有什么用?虽然线程比进程更轻量级,但是每个进程所占的资源空间是有限,如果我们频繁创建和销毁线程也会消耗很多CPU资源,那么我们该如何解决这个问题呢?官方解释:线程池是一种多线程处理形式,其处理过程可以将多个任务添加到阻塞队列…

电子招标采购系统:营造全面规范安全的电子招投标环境,促进招投标市场健康可持续发展

营造全面规范安全的电子招投标环境&#xff0c;促进招投标市场健康可持续发展 传统采购模式面临的挑战 一、立项管理 1、招标立项申请 功能点&#xff1a;招标类项目立项申请入口&#xff0c;用户可以保存为草稿&#xff0c;提交。 2、非招标立项申请 功能点&#xff1a;非招标…

Google巨大漏洞让Win10、11翻车,小姐姐马赛克白打了

早年间电脑截图这项技能未被大多数人掌握时&#xff0c;许多人应该都使用过手机拍屏幕这个原始的方式。 但由于较低的画面质量极其影响其他用户的观感&#xff0c;常常受到大家的调侃。 但到了 Win10、11 &#xff0c;预装的截图工具让门槛大幅降低。 WinShiftS 就能快速打开…

专业护眼灯什么牌子好?分享最专业护眼灯品牌排行

在日常生活中&#xff0c;照明灯具为人们提供了很多便利&#xff0c;但是对于长时间在灯光下用眼的学生跟办公族来说&#xff0c;容易导致用眼疲劳&#xff0c;甚至头晕等现象&#xff0c;所以现在普遍许多家庭都必备有护眼灯&#xff0c;能对眼睛起到缓解疲劳的作用&#xff0…

Docker安装Mysql集群(主从复制)

Docker安装Mysql集群(主从复制) 配置阿里云镜像 sudo vim /etc/docker/daemon.json插入如下镜像 {"registry-mirrors": ["https://sdiz8d27.mirror.aliyuncs.com"] }重启docker sudo systemctl daemon-reloadsudo systemctl restart docker保证images有…

python

好处 相对其他编程语言 比较简洁丰富的第三方库【做爬虫、机器学习、深度学习】 numpypandasmatplotlit用处 数据分析web开发游戏开发AI【比较广泛】安装部署python环境 1.官网下载python安装包【原生部署】 官网&#xff1a;python.org2.安装anaconda 1.自带python环境2.有丰富…