【二叉树】常见题目解析(2)

题目1:104. 二叉树的最大深度 - 力扣(LeetCode)

题目1描述:

题目1分析及解决:

        (1)base case:当前节点为null时,以当前节点为根节点的树最大深度是0。

        (2)节点不为null时,节点应该统计左右子树的最大深度,并在其中取一个最大值 + 1即可得到以当前节点为根节点的树最大深度是多少(+ 1是因为当前节点也算一个深度)。

        (3)既然要用到左右子树的递归结果,那么肯定是后序遍历整颗树。

        Code:

class Solution {
    public int maxDepth(TreeNode root) {
        //空树最大深度为0
        if(root == null)
        return 0;
        
        //获取左右子树的最大深度
        int leftDepth = maxDepth(root.left);
        int rightDepth = maxDepth(root.right);
        
        //在左右子树的结果中选一个较大值 + 1(当前节点也算一个深度)
        return Math.max(leftDepth,rightDepth) + 1;
    }
}

题目2:111. 二叉树的最小深度 - 力扣(LeetCode)

题目2描述:

题目2分析与解决:

        (1)base case:当前节点为null时,最小深度是0;当节点的左、右子节点都为null时,说明当前节点是叶子节点,最小深度是1.

        (2)节点不为null时,如果当前节点的左节点不为null,就获取左节点的最小深度;如果当前节点的右节点不为null,就获取右节点的最小深度;最后在左、右子节点返回的结果中选一个较小值 + 1即可得到以当前节点为根节点的树最小深度是多少。

        (3)由于还是要获取左、右子节点的返回结果,所以仍然是后序遍历。为什么要在左、右子节点不为null时,才能去递归获取他们的最小深度呢?看下图

        总结:不加if判断会被空节点影响最终结果。

        Code:

class Solution {
    public int minDepth(TreeNode root) {
        //节点为null时,最小深度是0
        if(root == null)
        return 0;
        
        //节点为叶子节点时,最小深度是1
        if(root.left == null && root.right == null)
        return 1;

        int leftDepth = Integer.MAX_VALUE;
        int rightDepth = Integer.MAX_VALUE;

        if(root.left != null)
        leftDepth = minDepth(root.left);

        if(root.right != null)
        rightDepth = minDepth(root.right);

        return Math.min(leftDepth,rightDepth) + 1;
    }
}

题目3:958. 二叉树的完全性检验 - 力扣(LeetCode)

题目3描述:

题目3分析与解决:

        (1)完全二叉树的特点如下图所示:

        (2)逐层遍历每一个节点(bfs),当一个节点的左子节点为null而右子节点不为null时,说明不是完全二叉树。

        (3)当遍历到一个节点,它的左、右子结点有一个为null,若后续节点不是叶子节点,说明不是完全二叉树。如下图所示,遍历到a节点时,其左子节点不为null、右子节点为null;后面遍历b节点时,如果b是叶子节点,则不破坏完全二叉树的性质,如果b不是叶子节点,则中间有空缺,不符合完全二叉树的定义。

        Code:

class Solution {
    
    //题目规定节点个数在100以内
    public static int MAX = 101;    
    
    //用数组模拟队列
    public static TreeNode [] queue = new TreeNode[MAX];

    //用head、tail两个变量维护队列的长度及出入队顺序
    public static int head,tail;
    public boolean isCompleteTree(TreeNode root) {
        //空树也是完全二叉树
        if(root == null)
        return true;

        //初始队列大小为0
        head = tail = 0;

        //根节点入队
        queue[tail++] = root;
        
        //标记变量:遍历到一个节点,只要它的左、右子节点有一个为null,就设置为true
        boolean flag = false;

        //队列不为空
        while(head < tail){
            //弹出队头节点
            TreeNode node = queue[head++];
            
            //返回false的两个条件,满足一个即可
            //1.左子节点为null的同时右子节点不为null
            //2.有节点设置flag为true的同时当前节点不是叶子节点
            if((node.left == null && node.right != null) ||
                (flag && (node.left != null || node.right != null))
            )
                return false;

            if(node.left != null)
            queue[tail++] = node.left;

            if(node.right != null)
            queue[tail++] = node.right;

            if(node.left == null || node.right == null)
            flag = true;
        }
            //如果逐层遍历过程中没有返回false,那么这棵树是完全二叉树,返回true
            return true;
    }
}

题目4:222. 完全二叉树的节点个数 - 力扣(LeetCode)

题目4描述:

题目4分析与解决:

        (1)最基本的思路是:递归左、右子树获取他们的节点个数,当递归到叶子节点时,就返回1(叶子节点的左、右子节点都为null),每层节点收集左、右子树的递归结果再 + 1(当前结点也算一个结点)返回即可。

        (2)基于上述思路无论是什么类型的二叉树都能统计其结点个数,但题目强调了是一颗完全二叉树,我们该如何利用这一性质?根据题目3我们知道,一颗完全二叉树不一定是一颗满二叉树,但它一部分的子树一定是一颗满二叉树;利用这一性质,当我们发现以当前结点为根节点的树是满二叉树时,直接计算结点个数返回,无需获取左、右子树的递归结果,减少时间复杂度

        (3)一颗满二叉树的结点个数如何计算呢? 不就是2^层数 - 1吗? 所以当我们递归到一个结点时,我们首先判断它是否是一颗满二叉树,是则直接计算结点个数;不是,则递归左、右子树,获取左、右子树的递归结果,再+1即可。

        Code:

class Solution {
    public int countNodes(TreeNode root) {
        //空结点肯定不算一个结点
        if(root == null)
        return 0;

        TreeNode l = root.left;
        int leftDepth = 0;
        //一直往左树遍历,看最深是多少
        while(l != null){
            l = l.left;
            leftDepth++;
        }
        TreeNode r = root.right;
        int rightDepth = 0;
        //一直往右树遍历,看最深是多少
        while(r != null){
            r = r.right;
            rightDepth++;
        }
        
        //如果左、右子树的深度相同
        //说明以当前结点为根节点的树是一颗满二叉树,直接计算结点个数并返回
        if(leftDepth == rightDepth)
        return (2 << leftDepth) - 1;
        else
        //否则获取左、右子树的递归结果 + 1 返回
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}

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

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

相关文章

【C/PTA —— 13.指针2(课外实践)】

C/PTA —— 13.指针2&#xff08;课外实践&#xff09; 一.函数题6-1 鸡兔同笼问题6-2 冒泡排序6-3 字符串反正序连接6-4 计算最长的字符串长度6-5 查找星期 二.编程题7-1 C程序设计 实验5-7 数组指针作函数参数7-2 查找奥运五环色的位置 一.函数题 6-1 鸡兔同笼问题 int Chic…

Nginx反向代理详解

Nginx反向代理详解 nginx反向代理是一种常用的服务器架构设计方案&#xff0c;其原理是将客户端请求先发送到反向代理服务器&#xff0c;反向代理服务器再将请求转发到后端真实服务器处理&#xff0c;并将处理结果返回给客户端&#xff0c;从而实现负载均衡、高可用、安全和减…

VSC++: 双进制回文

缘由双进制回文数&#xff0c;一道C程序题&#xff0c;求解&#xff01;&#xff01;&#xff01;&#xff1f;_编程语言-CSDN问答 int 合成100回文(int 数) { int 合 0, 倒 数>10 && 数 < 100 ? 数 / 10 : 数;while (倒)合 * 10, 合 倒 % 10, 倒 / 10, (合…

.net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法

文章目录 .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法详细报错内容解决方案修改数据修改表修改字段 .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法 详细报错内容 System.NotSupportedException…

Elasticsearch分词器--空格分词器(whitespace analyzer)

介绍 文本分析&#xff0c;是将全文本转换为一系列单词的过程&#xff0c;也叫分词。analysis是通过analyzer(分词器)来实现的&#xff0c;可以使用Elasticearch内置的分词器&#xff0c;也可以自己去定制一些分词器。除了在数据写入时将词条进行转换&#xff0c;那么在查询的时…

使用策略模式彻底消除if-else

文章目录 使用策略模式彻底消除if-else1. 场景描述2. if-else方式3. 策略模式 使用策略模式彻底消除if-else 如果一个对象有很多的行为&#xff0c;如果不用恰当的模式&#xff0c;这些行为就只好使用多重的条件选择语句来实现&#xff0c;这样会显得代码逻辑很臃肿&#xff0c…

C++学习之路(十五)C++ 用Qt5实现一个工具箱(增加16进制颜色码转换和屏幕颜色提取功能)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《Base64图片编码预览功能》功能。为了继续丰富我们的工具箱&#xff0c;今天我们就再增加两个平时经常用到的功能吧&#xff0c;就是「 16进制颜色码转RGB文本 」和 「屏幕颜色提取」功能。下面我们就来看看如何来规划…

LiveGBS流媒体平台GB/T28181功能-概览中负载信息直播、回放、播放、录像、H265、级联查看负载会话列表

LiveGBS常见问题-概览中负载信息具体表示什么直播、回放、播放、录像、H265、级联等 1、负载信息2、负载信息说明3、会话列表查看3.1、会话列表 4、搭建GB28181视频直播平台 1、负载信息 实时展示直播、回放、播放、录像、H265、级联等使用数目 2、负载信息说明 直播&#x…

MATLAB 模型参考自适应控制 - Model Reference Adaptive Control

系列文章目录 文章目录 系列文章目录前言一、参考模型二、扰动与不确定性模型三、直接 MRAC名义模型参数更新间接 MRAC估计器模型和控制器增益参数更新学习修正参考文献 前言 模型参考自适应控制模块计算控制动作&#xff0c;使不确定的受控系统跟踪给定参考被控对象模型的行为…

从0开始学习JavaScript--JavaScript 单元测试

JavaScript单元测试是保障代码质量和可维护性的关键步骤之一。通过编写和运行单元测试&#xff0c;开发者可以确保代码在不断迭代的过程中依然具有正确的行为。本文将深入探讨JavaScript单元测试的核心概念、工具使用和最佳实践&#xff0c;并通过丰富的示例代码演示其实际应用…

PgSQL技术内幕 • statement_timeout做的那些事

PgSQL技术内幕 • statement_timeout做的那些事 statement_timeout是Postgres种的一个配置参数&#xff0c;用于指定SQL语句执行的超时时间&#xff0c;当超时时就取消该SQL的执行&#xff0c;并返回错误信息。这个参数通常用于控制运行时间较长的查询&#xff0c;避免影响数据…

STM32CubeIDE(CUBE-MX hal库)----蓝牙模块HC-05(详细配置)

系列文章目录 STM32CubeIDE(CUBE-MX hal库)----初尝点亮小灯 STM32CubeIDE(CUBE-MX hal库)----按键控制 STM32CubeIDE(CUBE-MX hal库)----串口通信 STM32CubeIDE(CUBE-MX hal库)----定时器 文章目录 系列文章目录前言一、蓝牙配置二、CUBE-MX可视化配置三、蓝牙APP调试助手四、…

微信小程序 地图撒点

1. 微信小程序 地图撒点 1.1 说明 首先使用微信小程序自带标签&#xff0c;并且设置好宽高让地图显示&#xff0c;用longitude和latitude表示中心点。   &#xff08;1&#xff09;show-location 显示带有方向的当前定位点,本项目不需要不添加。   &#xff08;2&#xff…

组合(回溯+剪枝、图解)

77. 组合 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 样例输入 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],…

【算法】单调栈题单——字典序最小⭐(一种类型的模板题)

文章目录 题目列表316. 去除重复字母⭐⭐⭐⭐⭐&#xff08;类型题模板&#xff1a;单调栈&#xff0c;字典序最小&#xff09;221021天池-03. 整理书架&#xff08;保留数量为 limit 的字典序最小&#xff09;402. 移掉 K 位数字&#xff08;最多删除 k 次 前导零的处理&…

mysql主从复制-redis集群扩容缩容、缓存优化(缓存更新策略、穿透,击穿,雪崩)、mysql主从搭建、django实现读写分离

基于Docker实现读写分离 1 redis集群扩容缩容 1.1 集群扩容 1.2 集群缩容 2 缓存优化 2.1 缓存更新策略 2.2 穿透&#xff0c;击穿&#xff0c;雪崩 3 mysql主从搭建 4 django实现读写分离 1 redis集群扩容缩容 1.1 集群扩容 # 6台机器&#xff0c;3个节点集群# 8台机器&am…

hbase thrift2 jar包冲突导致启动失败问题排查记录

1、启动命令 ${HBASE_HOME}/bin/hbase-daemon.sh start thrift2 2、异常情况 hbase-root-thrift2-hdfs-test07.yingzi.com.out异常日志&#xff1a; Exception in thread "main" java.lang.AbstractMethodError: org.apache.hadoop.metrics2.sink.timeline.Hadoo…

TextToSpeech类学习和简单封装

TextToSpeech类简单学习封装 前言一、TTS是什么&#xff1f;二、TextToSpeech简单使用1.官方介绍2.简单使用 三、TextToSpeech简单封装总结 前言 业务涉及到对接TTS相关&#xff0c;所以简单学习下如何使用。 一、TTS是什么&#xff1f; TextToSpeech简称为TTS&#xff0c;即…

[网鼎杯 2020 青龙组]singal 1

前言 在主函数中找到了一个vm的译码器&#xff0c;译码器主要是解释传入的opcode&#xff0c;然后对我们输入的字符操作&#xff0c;这里我们发现他是单字节比较的&#xff0c;方法很多可以使用单字节映射&#xff0c;也可以是使用符号化执行&#xff0c;当然也可以硬着头皮去…

软件测试计划书

测试计划书 1.测试参考文档和测试提交文档 2.测试进度计划 3.测试资源 4.系统风险、优先级 5.测试策略 6.缺陷管理 7.测试停止标准 软件开发全文档下载进入主页。