二叉树的层序遍历经典问题(算法村第六关白银挑战)

news2024/11/16 13:33:54

基本的层序遍历与变换

二叉树的层序遍历

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

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

示例 1:

img

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

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]
public static List<List<Integer>> levelOrder(TreeNode root)
{
    //特判,否则queue.offer(root)会抛出NullPointerException
    if (root == null)
        return new ArrayList<List<Integer>>();

    ArrayList<List<Integer>> ans = new ArrayList<>();

    ArrayDeque<TreeNode> queue = new ArrayDeque<>();
    queue.offer(root);

    while (!queue.isEmpty())
    {
       //获取当前层的结点个数
       int size = queue.size();
            
       //该层结点的值
       ArrayList<Integer> list = new ArrayList<>();

        //遍历当前层
        for (int i = 0; i< size; i++)
        {
            TreeNode t = queue.remove();
            list.add(t.val);

            if (t.left != null)
                queue.offer(t.left);
            if (t.right != null)
                queue.offer(t.right);
        }

        //将这一层结点的值加入答案
        ans.add(list);
    }

    return ans;
}

自底而上的层序遍历

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

给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

示例 1:

img

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

在遍历完一层节点之后,将存储该层节点值的列表 list 添加到结果列表 ans 的头部即可。

为了时间复杂度,ans 使用链式结构的结构。在 ans 头部添加一层节点值的列表 list 的时间复杂度是 O(1)

public List<List<Integer>> levelOrderBottom(TreeNode root)
{
    //特判,否则queue.offer(root)会抛出NullPointerException
    if (root == null)
        return new ArrayList<List<Integer>>();

    ArrayList<List<Integer>> ans = new ArrayList<>();

    ArrayDeque<TreeNode> queue = new ArrayDeque<>();
    queue.offer(root);

    while (!queue.isEmpty())
    {
        //获取当前层的结点个数
        int size = queue.size();

        //该层结点的值
        ArrayList<Integer> list = new ArrayList<>();

        //遍历当前层
        for (int i = 0; i< size; i++)
        {
            TreeNode t = queue.remove();
            list.add(t.val);

            if (t.left != null)
                queue.offer(t.left);
            if (t.right != null)
                queue.offer(t.right);
        }

        //将这一层结点的值插入答案的头部
        ans.add(0,list);
    }

    return ans;
}

锯齿形层序遍历

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

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

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[20,9],[15,7]]
用双端队列维护当前层节点的存储

双端队列可以队头或队尾插入元素。

层序遍历顺序不变,但对当前层节点的存储,我们维护一个变量 isOrderLeft ,记录结点存储是从左至右还是从右至左

  1. 若从左至右,则采用头插法。该层第一个元素在此层遍历结束后,会出现在list的末端
  2. 若从右至左,则采用尾插法。该层第一个元素在此层遍历结束后,会出现在list的首端

最后需要注意的是,往 ans 添加 list 时,需要转换一下 list 的类型

public List<List<Integer>> zigzagLevelOrder(TreeNode root)
    {
        //特判,否则queue.offer(root)会抛出NullPointerException
        if (root == null)
            return new ArrayList<List<Integer>>();

        ArrayList<List<Integer>> ans = new ArrayList<>();

        ArrayDeque<TreeNode> queue = new ArrayDeque<>();
        queue.offer(root);

        boolean isOrderLeft = true;

        while (!queue.isEmpty())
        {
            //获取当前层的结点个数
            int size = queue.size();

            //该层结点的值。用一个双端队列存储
            ArrayDeque<Integer> deque = new ArrayDeque<>();

            //遍历当前层
            for (int i = 0; i< size; i++)
            {
                TreeNode t = queue.remove();

                if (isOrderLeft)
                    deque.offerLast(t.val);
                else
                    deque.offerFirst(t.val);

                if (t.left != null)
                    queue.offer(t.left);
                if (t.right != null)
                    queue.offer(t.right);
            }

            //这一层结点的值经过转换后加入答案
            ans.add(new LinkedList<>(deque));

            isOrderLeft = !isOrderLeft; //交替进行
        }

        return ans;
    }

N叉树的层序遍历

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

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。

树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

示例 1:

img
输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]

示例 2:

img
输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]
结点类型
public class Node
{
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
}
public List<List<Integer>> levelOrder(Node root)
{
    //特判,否则queue.offer(root)会抛出NullPointerException
    if (root == null)
        return new ArrayList<List<Integer>>();

    ArrayList<List<Integer>> ans = new ArrayList<>();

    ArrayDeque<Node> queue = new ArrayDeque<>();
    queue.offer(root);

    while (!queue.isEmpty())
    {
        //获取当前层的结点个数
        int size = queue.size();

        //该层结点的值
        ArrayList<Integer> list = new ArrayList<>();

        //遍历当前层
        for (int i = 0; i< size; i++)
        {
            Node t = queue.remove();
            list.add(t.val);

            //将当前结点的所有孩子加入队列
            for (Node child : t.children)
            {
                queue.offer(child);
            }
        }

        //将这一层结点的值加入答案
        ans.add(list);
    }

    return ans;
}

处理每层元素

在每个树行中找最大值

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

给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

示例1:

img
输入: root = [1,3,2,5,3,null,9]
输出: [1,3,9]
维护每层的最大值即可
public List<Integer> largestValues(TreeNode root)
{
    //特判,否则queue.offer(root)会抛出NullPointerException
    if (root == null)
        return new ArrayList<>();

    //存储每层结点的最大值
    ArrayList<Integer> list = new ArrayList<>();

    ArrayDeque<TreeNode> queue = new ArrayDeque<>();
    queue.offer(root);

    while (!queue.isEmpty())
    {
        //获取当前层的结点个数
        int size = queue.size();

        //当前层结点的最大值
        int maxOfLevel = Integer.MIN_VALUE;

        //遍历当前层
        for (int i = 0; i< size; i++)
        {
            TreeNode t = queue.remove();

            maxOfLevel = Math.max(maxOfLevel, t.val);

            if (t.left != null)
                queue.offer(t.left);
            if (t.right != null)
                queue.offer(t.right);
        }

        list.add(maxOfLevel);
    }

    return list;
}

二叉树的层平均值

637. 二叉树的层平均值 - 力扣(LeetCode)

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。

示例 1:

img

输入:root = [3,9,20,null,null,15,7]
输出:[3.00000,14.50000,11.00000]
解释:第 0 层的平均值为 3,1 层的平均值为 14.5,2 层的平均值为 11 。
因此返回 [3, 14.5, 11]
public List<Double> averageOfLevels(TreeNode root)
{
    //特判,否则queue.offer(root)会抛出NullPointerException
    if (root == null)
        return new ArrayList<>();

    //存储每层结点的最大值
    ArrayList<Double> list = new ArrayList<>();

    ArrayDeque<TreeNode> queue = new ArrayDeque<>();
    queue.offer(root);

    while (!queue.isEmpty())
    {
        //获取当前层的结点个数
        int size = queue.size();

        //当前层结点值的和
        double sum = 0;

        //遍历当前层
        for (int i = 0; i< size; i++)
        {
            TreeNode t = queue.remove();

            sum += t.val;

            if (t.left != null)
                queue.offer(t.left);
            if (t.right != null)
                queue.offer(t.right);
        }
		
        //计算平均值并添加到列表
        list.add(sum / size);
    }

    return list;
}

二叉树的右视图

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

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

示例 1:

img

输入: [1,2,3,null,5,null,4]
输出: [1,3,4]

层序遍历,记录每层最后一个元素即可

public List<Integer> rightSideView(TreeNode root)
{
    //特判,否则queue.offer(root)会抛出NullPointerException
    if (root == null)
        return new ArrayList<>();

    //存储每层的最后一个结点
    ArrayList<Integer> list = new ArrayList<>();

    ArrayDeque<TreeNode> queue = new ArrayDeque<>();
    queue.offer(root);

    while (!queue.isEmpty())
    {
        //获取当前层的结点个数
        int size = queue.size();

        //遍历当前层
        for (int i = 0; i < size; i++)
        {
            TreeNode t = queue.remove();

            //记录当前层最后一个元素
            if (i == size - 1)
                list.add(t.val);

            if (t.left != null)
                queue.offer(t.left);
            if (t.right != null)
                queue.offer(t.right);
        }
    }

    return list;
}

最底层最左边的结点

513. 找树左下角的值 - 力扣(LeetCode)

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

示例 1:

img

输入: root = [2,1,3]
输出: 1

示例 2:

img
输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7
从右往左层序遍历

从右向左层次遍历, 最后一个访问的节点必然是最底层最左侧叶子节点。只需调整一下左右孩子加入队列的次序即可

public int findBottomLeftValue(TreeNode root)
{
    ArrayDeque<TreeNode> queue = new ArrayDeque<>();
    queue.offer(root);

    TreeNode t = null;

    while (!queue.isEmpty())
    {
        //获取当前层的结点个数
        int size = queue.size();

        //遍历当前层
        for (int i = 0; i < size; i++)
        {
            t = queue.remove();

            //右孩子先于左孩子放入队列
            if (t.right != null)
                queue.offer(t.right);
            if (t.left != null)
                queue.offer(t.left);
        }
    }

    return t.val;   //返回最底层最右边的结点的值
}

左叶子之和

404. 左叶子之和 - 力扣(LeetCode)

给定二叉树的根节点 root ,返回所有左叶子之和。

示例 1:

img

输入: root = [3,9,20,null,null,15,7] 
输出: 24 
解释: 在这个二叉树中,有两个左叶子,分别是 915,所以返回 24

提示:

  • 节点数在 [1, 1000] 范围内

广度优先遍历

在BFS的过程中添加一个判断是否为左叶子结点的条件语句即可

public int sumOfLeftLeaves(TreeNode root)
{
    int answer = 0;

    ArrayDeque<TreeNode> queue = new ArrayDeque<>();
    queue.offer(root);


    while (!queue.isEmpty())
    {
        //获取当前层的结点个数
        int size = queue.size();

        //遍历当前层
        for (int i = 0; i < size; i++)
        {
            TreeNode t = queue.remove();

            if (t.left != null)
            {
                //如果t的左孩子是叶子结点
                if(t.left.left == null && t.left.right == null)
                    answer += t.left.val;
                else
                    queue.offer(t.left);
            }
            if (t.right != null)
                queue.offer(t.right);

        }
    }

    return answer;
}

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

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

相关文章

kubernetes 审计与日志 详解

开头语 写在前面&#xff1a;如有问题&#xff0c;以你为准&#xff0c; 目前24年应届生&#xff0c;各位大佬轻喷&#xff0c;部分资料与图片来自网络 内容较长&#xff0c;页面右上角目录方便跳转 基本 介绍 在Kubernetes集群中&#xff0c;API Server的审计日志记录了…

golang实现加密解密文档

golang实现加密解密文档 package mainimport ("bytes""crypto/aes""crypto/cipher""crypto/rand""encoding/base64""flag""fmt""io""io/ioutil" )func main() {encodePtr : flag.…

过去半年信竞基础学习总结

当Richard同学从去年7月份&#xff0c;开始从YY班学习C和信息学竞赛时&#xff0c;他对C还一无所知&#xff0c;但对计算机和编程的兴趣让他一直都乐在其中。在过去的半年中&#xff0c;通过参加各个平台的月赛&#xff0c;让他更加热爱编程&#xff0c;也让Richard更加了解自己…

linux项目部署(jdk,tomcat,mysql,nginx,redis)

打开虚拟机&#xff0c;与连接工具连接好&#xff0c;创建一个文件夹 cd /tools 把jdk,tomcat安装包放入这个文件夹里面 #解压 tar -zxvf apache-tomcat-8.5.20.tar.gz #解压jdk tar -zxvf jdk-8u151-linux-x64.tar.gz 编辑jdk文件以及测试jdk安装 第一行代码路径记得改成我…

服务器里面打开浏览器访问不了会是什么原因

我们在日常使用服务器的过程中&#xff0c;时常会有遇到各类情况&#xff0c;近日就有遇到用户联系到德迅云安全&#xff0c;反馈自己在服务器里面打不开浏览器&#xff0c;服务器里面没有网络无法访问的情况。那我们今天就来讲下服务器里面打不开网站可能是由哪些原因导致。 …

可充电助听器有哪些优势?

可充电助听器有哪些优势 01 无需频繁更换电池&#xff0c;对于手指不灵活、眼神不好的老年用户以及无法自行更换电池的儿童用户&#xff0c;使用更为方便。 02 可充电助听器的电池一般密封在助听器内部&#xff0c;机身的防水防尘性能更强。 03 部分充电盒具有快充、储电、…

GC5958Q—三相无刷直流电机速度控制芯片,应用在静音风扇马达上,可替代APX9358/茂达

GC5958Q提供无传感器三相无刷直流电机速度控制的所有电路。正弦波驱动器的方法将是更好的低噪声。该控制器的功能包括启动电路&#xff0c;反电动势换向控制&#xff0c;脉冲宽度调制(PWM)速度控制&#xff0c;锁定保护&#xff0c;和热关断电路。该GC5958Q是适用于游戏机和CPU…

一夜爆火,3天60亿,这泼天的富贵也轮到我们尔滨了

近日&#xff0c;哈尔滨这座北国之城突然成为全国瞩目的焦点&#xff0c;一夜之间&#xff0c;冰雪大世界、索菲亚大教堂、中央大街等老牌旅游景点在网络短视频和游客们的热切关注下&#xff0c;成为了这个冬季的新“顶流”。当地市民姚先生和胡先生异口同声表示&#xff1a;“…

服务发现Discovery

对于注册进eureka里面的微服务&#xff0c;可以通过服务发现来获得该服务的信息 1、 修改cloud-provider-payment8001的controller import com.my.springcloud.utils.RestResponse; import com.my.springcloud.entities.Payment; import com.my.springcloud.service.PaymentSe…

关于外连接、内连接和子查询的使用(2)

目录 一. 前言 二. 使用外连接、内连接和子查询进行解答 三. 思维导图 一. 前言 在前面我们对外连接、内连接和子查询的使用有了一些了解&#xff0c;今天我们将继续更深入的进行学习。&#xff08;这里缺少的八个题目在博主的前面博客有解答&#xff0c;大家可以移步前面一…

科技稳田心:地震频发,珈和科技领跑农险业务全流程

近日&#xff0c;日本能登半岛发生7.6级地震&#xff0c;13年以来首次触发“大海啸警报”。据估算&#xff0c;上一次的“3.11日本大地震”&#xff0c;导致了农林水产业损失约1200亿元。 自然灾害正严重影响着农业生产和可持续发展&#xff0c;提高农民抗风险能力&#xff0c…

知识图谱gds使用记录

安装 从下载站下载对应的包到plugin目录下&#xff0c;修改配置文件/etc/neo4j/neo4j.conf&#xff0c;末尾加入gds.*&#xff0c;重新启动 在浏览器输入CALL gds.list()命令进行测试 建立图映射 为了使用图算法&#xff0c;需要先将图数据库的内容映射为一个新图 如果是全…

国标GB28181视频监控EasyCVR平台:视频集中录制存储/云端录像功能及操作介绍

安防视频监控系统EasyCVR视频综合管理平台&#xff0c;采用了开放式的网络结构&#xff0c;可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云存储等丰富的视频能力&#xff0c;同时还具备权限管理、设…

微信预约小程序制作指南:从小白到专家

在当今的数字时代&#xff0c;微信小程序已经成为了一种非常流行的应用方式。预约功能更是成为了许多小程序的核心功能之一。如果你也想为你的小程序添加预约功能&#xff0c;以下步骤将会对你有所帮助。 一、进入乔拓云网后台 乔拓云网是一个在线小程序开发平台&#xff0c;你…

熟悉HDFS常用操作

1. 利用Hadoop提供的Shell命令完成下列任务 (1)向HDFS中上传任意文本文件,如果指定的文件在HDFS中已经存在,由用户指定是追加到原有文件末尾还是覆盖原有的文件。 #检查文件是否存在./bin/hdfs dfs -test -e text.txt echo $? #结果是1 代表已存在 #根据结果判断出文件已存…

OpenHarmony自定义Launcher

前言 OpenHarmony源码版本:4.0release 开发板:DAYU / rk3568 DevEco Studio版本:4.0.0.600 自定义效果: 一、Launcher源码下载 Launcher源码地址:https://gitee.com/openharmony/applications_launcher 切换分支为OpenHarmony-4.0-Release,并下载源码 二、Launcher源…

[AutoSar]基础部分 RTE 08 runnable mapping

目录 关键词平台说明一、runnable mapping的必要性二、runnable mapping 通用规则三、Task type四、可以不用mapping的runnbale 关键词 嵌入式、C语言、autosar、runnable 平台说明 项目ValueOSautosar OSautosar厂商vector芯片厂商TI编程语言C&#xff0c;C编译器HighTec (…

动能芯片|DP1332E多协议高度集成非接触式读写芯片

DP1332E是一个高度集成的非接触读写芯片&#xff0c;它包含80C51微控制器内核&#xff0c;集成了13.56MHz下的各种主动/被动式非接触通信方法和协议。DP1332E有丰富的通讯接口和多协议集成优势&#xff0c;支持ISO/IEC18092,可以极大减少研发成本&#xff0c;高效、灵活的推动项…

铁威马使用小贴士,让NAS实现存储的旷野

结束2024年的第一个假期&#xff0c;我们忙着做年终总结&#xff0c;对来年许下希冀。 2023毋庸置疑是近年来过得较为丰富多彩的一年。 “看了好多场演唱会” “实现了一场说走就走的旅行” “蹦一场无拘无束的音乐节” “去见了很多很多好朋友” “去探索属于我人生的旷…

TS 36.213 V12.0.0-PUSCH相关过程(5)-UE PUSCH hopping过程

​本文的内容主要涉及TS 36.213&#xff0c;版本是C00&#xff0c;也就是V12.0.0。