代码随想录算法训练营第16天 |● 104.二叉树的最大深度 559.n叉树的最大深度 ● 111.二叉树的最小深度 ● 222.完全二叉树的节点个数

news2024/11/18 9:40:24

文章目录

  • 前言
  • 104.二叉树的最大深度
    • 思路
      • 知识点
    • 方法一 递归法
    • 方法二 迭代法
  • 559. n叉树的最大深度
  • 111.二叉树的最小深度
    • 思路
    • 方法一 后向遍历递归法
    • 方法二 迭代法
  • 222.完全二叉树的节点个数
    • 思路
    • 方法一 当成普通二叉树来做
    • 方法二 利用完全二叉树的特性
  • 总结


前言

所有的题目一刷都是优先掌握递归,迭代法没看,记不住。打十个做完之后再说吧
104和111没有看先序遍历的代码

104.二叉树的最大深度

在这里插入图片描述

思路

知识点

记住深度和高度的定义:1. 从1开始 计数 2. 深度和高度与我们主观常识一致
在这里插入图片描述

总体思路:求解最大深度就是求解根节点的高度;💛

因为求深度是前序遍历,求高度是后序遍历【在子节点的高度上加1就是根节点的高度】,后序遍历要比前序遍历在本题中简洁一些,所以本题使用后序遍历的求高度;
💟具体实现细节:单层递归中求解的逻辑是,当前节点的高度为子节点高度+1;【递归法的第三步】
递归三部曲
在这里插入图片描述
先序遍历有c++代码,非常直观的从上往下的递归。也可以看

方法一 递归法

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        def getheight(root):
            if not root: return 0
            height_left = getheight(root.left)
            height_right =getheight(root.right)
            height = 1+max(height_left,height_right)
            return height
        
        return getheight(root)
###精简版
class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
      
        if not root: return 0
        return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))

方法二 迭代法

559. n叉树的最大深度

这题目我也刷了

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        if not root:
            return 0
        
        max_depth = 1
        
        for child in root.children:
            max_depth = max(max_depth, self.maxDepth(child) + 1)
        
        return max_depth

111.二叉树的最小深度

在这里插入图片描述

思路

总体思路:与上面的最大深度差不多,但是不能单纯将max改成min。

  • 如果直接max改成min的话,例如下面的最右边的节点6会被算成高度为1,因为min子节点的结果为0,也就是将6当成叶子了;或者按照老师讲解的,根节点中会算左边的null为0.,这样最小深度就是1了。
    下面是老师的讲解
    在这里插入图片描述

  • 所以这条题目相较于104的改动就是加上分类讨论:(这是递归法的第三步单层逻辑)

    • 子节点中,一个是null,一个有节点,按照有节点的那个算
    • 两个都有的话选择min的那个
    • 两个都是空那就是0【可以与上面那个合并】
      在这里插入图片描述

方法一 后向遍历递归法

自己写的错误

  1. 在类里面调用递归的时候,记得加上self
  2. 下面是教程里面的代码,我写的时候is None用not来代替了,我觉着这样国家好一些
class Solution:
    def getDepth(self, node):
        if node is None:
            return 0
        leftDepth = self.getDepth(node.left)  # 左
        rightDepth = self.getDepth(node.right)  # 右
        
        # 当一个左子树为空,右不为空,这时并不是最低点
        if node.left is None and node.right is not None:
            return 1 + rightDepth
        
        # 当一个右子树为空,左不为空,这时并不是最低点
        if node.left is not None and node.right is None:
            return 1 + leftDepth
        
        result = 1 + min(leftDepth, rightDepth)
        return result

    def minDepth(self, root):
        return self.getDepth(root)

### 精简代码
class Solution:
    def minDepth(self, root):
        if root is None:
            return 0
        if root.left is None and root.right is not None:
            return 1 + self.minDepth(root.right)
        if root.left is not None and root.right is None:
            return 1 + self.minDepth(root.left)
        return 1 + min(self.minDepth(root.left), self.minDepth(root.right))

方法二 迭代法

222.完全二叉树的节点个数

在这里插入图片描述

思路

方法一 当成普通二叉树来做

注意:使用后序遍历的代码是最简洁的
先序遍历:参考104题目教程里面的先序遍历写法,明显会复杂一些,为啥呢,因为需要一个全局变量来++1
单层处理逻辑:后序遍历到这个节点时,已经遍历的节点个数为它的子节点个数之和+1
递归三步走:
在这里插入图片描述

每一个都需遍历一下,时间复杂度为O(n)

class Solution(object):
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root: return 0
        cright = self.countNodes(root.right)
        cleft = self.countNodes(root.left)
        return 1+cright+cleft

方法二 利用完全二叉树的特性

首先回顾完全二叉树定义:
在这里插入图片描述
总体思路:利用满二叉树如果知道深度为n,节点个数就是2**n-1的特性,避免遍历所有的节点;
递归第三步单层处理逻辑

  • 完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
    • 对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。

    • 对于情况二,左右孩子节点数之和加1

      • 左孩子,和右孩子的计算就是递归,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。

      在这里插入图片描述
      如何判断是否为完全二叉树:最左边一层和最右边一层节点数相同,这样就只需要遍历最外侧的就行
      在这里插入图片描述
      注意事项

  1. left和right侧边count的起始为1
  2. 2的阶数写为(2 << leftDepth) - 1 #注意(2<<1) 相当于2^2,所以leftDepth初始为0
class Solution(object):
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        # if not root: return 0
        # cright = self.countNodes(root.right)
        # cleft = self.countNodes(root.left)
        # return 1+cright+cleft
        if not root: return 0
        #判断是否为满二叉树
        left = root.left
        right = root.right
        left_height, right_height = 1,1# 注意这个是1
        while(left):
            left_height +=1
            left = left.left
        while(right):
            right_height += 1
            right = right.right
        if right_height == left_height:
            return 2**right_height -1
        
        cleft = self.countNodes(root.left)
        cright = self.countNodes(root.right)
        return 1+cleft+cright
        
#还有一种技巧计算2的阶数,这时起始height要计算为0;代码如下,
class Solution:
    def countNodes(self, root: TreeNode) -> int:
        if not root:
            return 0
        left = root.left
        right = root.right
        leftDepth = 0 #这里初始为0是有目的的,为了下面求指数方便
        rightDepth = 0
        while left: #求左子树深度
            left = left.left
            leftDepth += 1
        while right: #求右子树深度
            right = right.right
            rightDepth += 1
        if leftDepth == rightDepth:
            return (2 << leftDepth) - 1 #注意(2<<1) 相当于2^2,所以leftDepth初始为0
        return self.countNodes(root.left) + self.countNodes(root.right) + 1
 

更加简洁的写法:完全二叉树写法2【教程里面的】
两侧同时顺着边数,直到有一条边为none,然后依据是否同时到底来判断是否为满二叉树;

class Solution: # 利用完全二叉树特性
    def countNodes(self, root: TreeNode) -> int:
        if not root: return 0
        count = 1
        left = root.left; right = root.right
        while left and right:
            count+=1
            left = left.left; right = right.right
        if not left and not right: # 如果同时到底说明是满二叉树,反之则不是
            return 2**count-1
        return 1+self.countNodes(root.left)+self.countNodes(root.right) 

总结

比较有意思,今天都不想听申论课了。还是算法好玩。。。。可惜找不到工作

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

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

相关文章

最简单的,在mac笔记本上安装Unix-v6系统,进行“Unix内核源码剖析”

Unix V6 已经是 1975 年的系统了&#xff0c;但是其源代码拢共只有 1w 行左右&#xff0c;并且使用了 C 语言&#xff08;K & R 之前的标准&#xff09;&#xff0c;还是现代操作系统的鼻祖&#xff0c;所以说是初学者最好的研究对象。 安装模拟器 brew install simh …

U-Mail邮件系统取得多项适配认证,全面支持国产化信创环境

随着信息技术的发展&#xff0c;信息化建设越来越深入到社会各个领域&#xff0c;成为驱动经济社会发展的重要力量。在此背景下&#xff0c;我国正加快构建国家信息安全保障体系&#xff0c;实现自主可控&#xff0c;形成安全可靠的信息技术体系。这正是我们所说的“信创”&…

Mac上安装多版本nodejs 并 随意切换node版本

Mac上安装多版本nodejs 并 随意切换node版本 1. 先查看当前版本2. 说明3. 安装 n 组件4. 根据需要安装其他版本的node4.1 查看node历史版本4.2 安装指定版本的node4.2.1 使用n 组件安装多版本4.2.2 n 组件常用命令 4.3 也可以安装node14 1. 先查看当前版本 如下&#xff1a;no…

26【构图】场景透视 —— 一点透视

1 一点透视更能体现纵深 2 图中的 消失点 透视线 视平线的位置 3 一点透视模型 蓝色的是消失点&#xff0c;根据消失点发射出无数的透视线 在PS中可以用简单的方法画出一点透视的透视线&#xff08;通过多边形工具&#xff09;

电脑视频如何压缩变小 mp4视频太大怎么压缩不影响画质

视频格式是指用于存储、编码、解码和播放数字视频内容的特定文件类型和结构。它定义了视频数据的压缩方式、存储布局以及播放参数&#xff0c;确保不同的设备和软件能够识别并正确处理视频文件。视频格式包括两大部分视频编码格式和容器格式。 视频太大的话有时候上传不了&…

Android Audio基础——AudioFlinger回放录制线程(七)

AndioFlinger 作为 Android 的音频系统引擎,重任之一是负责输入输出流设备的管理及音频流数据的处理传输,这是由回放线程 PlaybackThread 及其派生的子类和录制线程 RecordThread 进行的。 一、基础介绍 1、关系图 ThreadBase:PlaybackThread 和 RecordThread 的基类。 Re…

DDoS攻击的最新动态及市场趋势分析

随着数字化转型的加速和网络连接设备的增加&#xff0c;分布式拒绝服务(Distributed Denial of Service, DDoS)攻击已经成为全球网络安全领域的一大威胁。根据最新的市场研究报告&#xff0c;预计到2028年&#xff0c;DDoS防护软件市场的复合年增长率将达到14%以上&#xff0c;…

工作站虚拟化:RTX A5000的图形工作站实现多用户独立运行Siemens NX 设计软件

一、背景 Siemens NX 是由西门子数字工业软件&#xff08;Siemens Digital Industries Software&#xff09;开发的一款先进的集成计算机辅助设计&#xff08;CAD&#xff09;、计算机辅助制造&#xff08;CAM&#xff09;和计算机辅助工程&#xff08;CAE&#xff09;软件。它…

Linux:Ubuntu修改root密码

Linux&#xff1a;Ubuntu修改root密码 修改默认grub配置文件 rootshanxin:~# vim /etc/default/grub# 主要修改内容如下&#xff1a;GRUB_DEFAULT0 #GRUB_TIMEOUT_STYLEhidden 注释这一行 GRUB_TIMEOUT5 # 将这一行的时间改为5秒进行开启启动的grub文件的复写 rootshanxin:~…

618精选编程书单推荐:优质知识提升你的代码力

前言 在这个快速发展的技术时代&#xff0c;不断学习和提升自己的编程技能是每位程序员的必修课。今天&#xff0c;我为大家精心挑选了一系列编程技术书籍&#xff0c;它们将是你技术成长道路上的宝贵财富。 文章目录 前言编程之路&#xff1a;为何阅读书籍是不可或缺的书籍的…

vue连接mqtt实现收发消息组件超级详细

基本概念&#xff1a; MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种基于发布/订阅模式的轻量级消息传输协议&#xff0c;专为低带宽、高延迟或不稳定的网络环境设计。以下是MQTT实现收发消息的基本原理&#xff1a; 客户端-服务器模型&#xff1a…

清华团队推出免费AI服务:与人类偏好对齐的大型语言模型

在人工智能领域&#xff0c;大型语言模型&#xff08;LLMs&#xff09;的迅猛发展极大地推动了机器在语言理解和生成方面的能力。然而&#xff0c;如何让这些模型更好地与人类偏好和价值观对齐&#xff0c;成为了一个重要而紧迫的课题。为此清华团队推出一项免费服务ChatGLM-RL…

EI会议的最佳论文奖是什么?如何申请?

EI会议的最佳论文奖通常是指在EI&#xff08;工程索引&#xff0c;Engineering Index&#xff09;收录的学术会议中&#xff0c;评选出的表现最优秀的论文奖项。以下是关于该奖项的一些基本信息及申请步骤&#xff1a; 最佳论文奖的含义 评选标准&#xff1a;最佳论文奖通常基…

Java-常见面试题收集(十六)

二十五 RocketMQ 1 消息队列介绍 消息队列&#xff0c;简称 MQ&#xff08;Message Queue&#xff09;&#xff0c;它其实就指消息中间件&#xff0c;当前业界比较流行的开源消息中间件包括&#xff1a;RabbitMQ、RocketMQ、Kafka。&#xff08;一个使用队列来通信的组件&…

【论文笔记】| 蛋白质大模型ProLLaMA

【论文笔记】| 蛋白质大模型ProLLaMA ProLLaMA: A Protein Large Language Model for Multi-Task Protein Language Processing Peking University Theme: Domain Specific LLM Main work&#xff1a; 当前 ProLLM 的固有局限性&#xff1a;&#xff08;i&#xff09;缺乏自然…

【竞技宝】欧洲杯:吉鲁退出法国队,欧洲杯后主动让贤

吉鲁是法国队功勋中锋&#xff0c;为球队立下过赫赫战功。法国队能在2018年拿到久违的世界杯冠军&#xff0c;吉鲁身为主力锋霸功不可没。每当&#xff0c;法国队在比赛中遇到僵局&#xff0c;吉鲁总会站出来&#xff0c;为球队做出应有的贡献。吉鲁在法国队的作用不仅仅体现在…

CPU进入内核,是什么意思?

知乎上有一个问题&#xff1a; 进入内核态究竟是什么意思&#xff1f; 暂且忘记这个问题&#xff0c;让我们从另一个问题出发&#xff0c;一步步引出这个问题的答案。 特权指令问题 现代计算机里面&#xff0c;同时运行了很多程序&#xff0c;比如Office软件、浏览器、QQ、还…

好书推荐|MATLAB科技绘图与数据分析

提升你的数据洞察力&#xff0c;用于精确绘图和分析的高级MATLAB技术 MATLAB科技绘图与数据分析——jd 本书内容 《MATLAB科技绘图与数据分析》结合作者多年的数据分析与科研绘图经验&#xff0c;详细讲解MATLAB在科技图表制作与数据分析中的使用方法与技巧。全书分为3部分&a…

Jetbrains插件AI Assistant,终于用上了

ai assistant激活成功后&#xff0c;如图 ai assistant获取&#xff1a;https://web.52shizhan.cn/activity/ai-assistant 主要功能如下

springboot集成达梦数据库8

springboot集成达梦数据库8 官方文档&#xff1a;[https://eco.dameng.com/document/dm/zh-cn/start/java-development.html](https://eco.dameng.com/document/dm/zh-cn/start/java-development.html) 引入maven依赖 <!--添加数据库驱动安装包--> <dependency> …