【Leetcode】代码随想录Day16|二叉树3.0

文章目录

    • 104 二叉树的最大深度
    • 559 n叉树的最大深度
    • 111 二叉树的最小深度
    • 222 完全二叉树的节点个数

104 二叉树的最大深度

  • 递归法:无论是哪一种顺序,标记最大深度
class Solution(object):def depthHelper(self, root, depth):if root:depth += 1left_depth = self.depthHelper(root.left, depth)right_depth = self.depthHelper(root.right, depth)return max(left_depth, right_depth)return depthdef maxDepth(self, root):depth = 0if root:depth = self.depthHelper(root, depth)return depth

优解参考简化:

class Solution(object):def maxDepth(self, root):if not root:return 0ldepth = self.maxDepth(root.left)rdepth = self.maxDepth(root.right)return max(ldepth,rdepth) + 1
  • 迭代法:层序遍历
class Solution:def maxDepth(self, root: TreeNode) -> int:if not root:return 0depth = 0queue = collections.deque([root])while queue:depth += 1for _ in range(len(queue)):node = queue.popleft()if node.left:queue.append(node.left)if node.right:queue.append(node.right)return depth

559 n叉树的最大深度

  • 递归法:需要遍历每个节点的children
"""
# Definition for a Node.
class Node(object):def __init__(self, val=None, children=None):self.val = valself.children = children
"""class Solution(object):def maxDepth(self, root):if not root:return 0childDepth = 0if root.children:childDepth = max([self.maxDepth(child) for child in root.children])return 1 + childDepth

111 二叉树的最小深度

初始思路
与最大深度一样

class Solution(object):def minDepth(self, root):if not root:return 0ldepth = self.minDepth(root.left)rdepth = self.minDepth(root.right)return min(ldepth,rdepth) + 1

问题:
最大深度只要有一个分支有更深的深度,取这个深度就可以了,所有累积到此的分支都是存在的,他们的深度代表了树的深度。但是上述方法中的最小分支却可能是树并不存在的分支,也就不能代表树的深度。如下面这个例子,这个树的深度是3,但是如果用与之前类似的方法,那么在1这个root左子树不存在的时候,就会认为找到了最短的路径深度1。事实上1并不是叶子结点,并不符合对与树深度的定义。所以在找最小路径的时候,要考虑找到的深度究竟能不能算做是整个树的深度。

      1\2/3 

转换思路:
需要判断分支深度为0的情况,如果有且只有一个分支深度为0,那么这个后面的深度是需要算上的,并不能因为其中一个分支深度为0,就在这里截止,当作最小深度的情况。

class Solution(object):def minDepth(self, root):if not root:return 0left = self.minDepth(root.left)right = self.minDepth(root.right)minDepth = 0if left == 0 and right != 0:minDepth = rightelif left != 0 and right == 0:minDepth = leftelse:return 1 + min(left, right)return 1 + minDepth

222 完全二叉树的节点个数

1. 初始思路
递归或迭代遍历所有节点

  • 递归
class Solution(object):def countNodes(self, root):if not root:return 0left = self.countNodes(root.left)right = self.countNodes(root.right)return left + right + 1

Complexity
time: O(n)
space: O(log n),算上了递归系统栈占用的空间

  • 迭代:

Complexity
time: O(n)
space: O(n)

2. 利用完全二叉树的特性

首先我们最想用的肯定是满二叉树,因为直接通过层数就可以算出来节点数量2^h - 1。 但是完全二叉树可能有两种情况:

  • 满二叉树
  • 距离满二叉树只有最后一层按顺序没有填满

为了能够利用简介的满二叉树算法,我们可以通过递归去将输入的树拆解成子满二叉树。对于一个完全二叉树来讲,会有两种拆解方式:
来自代码随想录

来自代码随想录

那么如何判断是否是满二叉树呢?
既然非满二叉树的完全二叉树只有可能是最后一层按照从左往右的顺序右边没有填满,那么只要查看一个树的最后一层的最左边的深度和最后一层的最右边的深度是否一样,就可以判断它是不是满的。

那么总结一下方法:就是往下递归找到最大块的满二叉树组成部分,来计算总共的节点数。

class Solution(object):def getFullHeight(self, root):# return -1 if it is not full# else, return the height of the full binary treeif not root:return 0left = 1right = 1lefttmp = rootrighttmp = rootwhile lefttmp.left:lefttmp = lefttmp.leftleft += 1while righttmp.right:righttmp = righttmp.rightright += 1if left == right:return leftreturn -1 def countNodes(self, root):if not root:return 0h = self.getFullHeight(root)if h == -1:return 1 + self.countNodes(root.left) + self.countNodes(root.right)return 2**h - 1

优解参考简化

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

优化二:将getFullHeight的操作明确只对剩下的一半进行,让另一半以O(1)的复杂度完成,不需要再判断一次满二叉树了。

class Solution:def countNodes(self, root):if not root:return 0leftDepth = self.getDepth(root.left)rightDepth = self.getDepth(root.right)if leftDepth == rightDepth:return pow(2, leftDepth) + self.countNodes(root.right)else:return pow(2, rightDepth) + self.countNodes(root.left)def getDepth(self, root):if not root:return 0return 1 + self.getDepth(root.left)

Complexity
time: O(log n × log n)
space: O(log n)

时间复杂度的解释
H为整个树的高度,n为总节点数。

  1. 判断是否为满二叉树及其深度的时间复杂度为O(H) = O(log n) 【getFullHeight】

  2. 从上面两种由满二叉树构成完全二叉树的方式中可以看出,root.right只有两种可能的高度,H-1或H-2

    • H-1: 少的这个高度就是root那一层,则root.left和root.right相同高度。也就是说,root.left一定是满二叉树,只需要O(1)就可以算出节点数,root.right需要进一步递归判断节点数。
    • H-2:不仅少了root一层的高度,root.left比root.right高一层。也就是说最后一层不满的叶子结点全部都在root.left的范围里面,需要进一步递归判断节点数,而root.right是一个满二叉树,只需要O(1)就可以算出节点数。
  3. 从最后优化版中可以看到,在H层中,递归到每一层的时候,都有一半是满二叉树,可以用O(1) 的方式直接计算出数量,只需要进行一次【getFullHeight】,即对于O(log n)层,每一层进行一次O(log n)的操作,复杂度为 O(log n × log n)

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

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

相关文章

HWOD:合并整型数组

一、知识点 合并整型数组目前有两种方法 合并数组并不一定需要真正的合并 1、下意识的方法 对两个整型数组分别排序,然后合并 2、不排序的方法 遍历两个数组,找出最小值,输出最小值。将两个数组中与最小值相等的位置置为超大值 重复以…

VBA_MF系列技术资料1-510

MF系列VBA技术资料1-510 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧,我参考大量的资料,并结合自己的经验总结了这份MF系列VBA技术综合资料,而且开放源码(MF04除外),其中MF01-0…

go限流、计数器固定窗口算法/计数器滑动窗口算法

go限流、计数器固定窗口算法/计数器滑动窗口算法 一、问题 问题1:后端接口只能支撑每10秒1w个请求,要怎么来保护它呢? 问题2:发短信的接口,不超过100次/时,1000次/24小时,要怎么实现&#xff…

豆瓣影评信息爬取 (爬虫)

代码块: from lxml import etree import requestsheaders{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0 }url_list[] for i in range(0,5):i*20urlsf"https:…

链表带环问题——leetcode环形链表1 2

证明链表带环 链表的带环问题指的是本该指向NULL的最后一个节点指向了之前的节点,导致链表成环,找不到尾结点的情况,那么我们该如何证明链表带环呢? 我们可以类比物理中的追及问题,让快慢指针同时走,两者相…

企微知识库是如何搭建的?这篇文章来解答

知识库在企业中发挥着至关重要的作用,它不仅能够存储和整理重要的工作资料,还能提高员工的工作效率,加强团队之间的协作。对于使用微信企业版(企业微信)的企业来说,搭建一个专门的知识库是极有必要的。本文…

ceph osd分组

一、前言 使用分组可以更好的管理osd,将不同类型的磁盘,分到不同的组中,例如hhd类型的osd分配到hhd组,ssd类型的osd分配到ssd组,将io要求不高的分配到hhd组做存储,io要求高的分配到ssd组做存储 二、配置 查…

ubuntu23.10.1 php8.2安装

1、更新镜像源 apt update2、安装php apt install php php-fpm php-mysql其他扩展包,在后面加个-可以查看,选择安装,我这里是php8.2版本 apt-get install php8.2- 2.1php与nginx结合 PHP-FPM的配置文件位于/etc/php/{PHP版本}/fpm/pool.d/www.conf;…

Springboot中为什么你能通过一小段代码来访问网页?

为什么你能通过一小段代码来访问网页 要明白这件事,首先要知道我们是如何访问网站的 访问网页的本质涉及多个技术层面,从用户输入网址到最终在浏览器上看到页面的过程包含了多个步骤: 域名解析:当你在浏览器中输入一个网址&…

4.19作业

1.总结二进制信号量和计数型信号量的区别,以及他们的使用场景。 二进制信号量:信号量的数值只有0和1。(用于共享资源的访问),用于同步互斥计数型信号量:计数型信号量的值一般是大于或者等于2(生…

字体反爬知识积累2

一、os模块中函数的应用 如何获取当前文件中所有文件的路径方法 这段代码使用 os.walk()函数来遍历指定目录 imgs 下的所有子目录和文件。具体来说,os.walk()函数返回一个生成器,可以在每次迭代中获取目录树中的一个元组,元组包含当前目录的…

MySQL--数据的增删改

目录 1.添加数据 1.1、添加全部字段的数据 1.2、添加指定字段的部分数据 1.3、同时添加多条记录 1.4、插入查询结果数据 2.修改数据 2.1、更新全部数据 2.2、更新部分数据 3.删除部分数据 3.1、删除部分数据 3.2、删除全部数据 文中[ ]里 面的内容可写可不写 1.添加数…

【Linux C | 多线程编程】线程同步 | 条件变量(万字详解)

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 ⏰发布时间⏰:2024-04-15 0…

电大搜题微信公众号:重庆开放大学学子的学习利器

在当今信息化时代,学习已经成为每个人不可或缺的一部分。然而,对于重庆开放大学的学子们来说,由于远程教育的特殊性,他们面临着更大的学习挑战。幸运的是,他们现在可以依靠一款强大的学习利器——电大搜题微信公众号&a…

单片机基础知识 07

一. 键盘检测 键盘分为编码键盘和非编码键盘。 编码键盘 :键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或者键值,如计算机键盘。 非编码键盘:靠软件编程来识别。 在单片机组成的各种系统中,用的较多的…

wsl + ubuntu + pycups + mqtt 远程打印入门

文章目录 wsl + ubuntu + pycups + mqtt 远程打印入门1. wsl安装python2. 安装pycups3. 打印机列表4. 查看API5. 打印文件6. mqtt配置7. mqtt对接参考wsl + ubuntu + pycups + mqtt 远程打印入门 这篇讲pycups 配合mqtt 做远程打印,cups 安装要看上一篇 windows10 下 wsl + u…

Darknet框架优化介绍

一、DarkNet框架简介 1.DarkNet的简介 Darknet是一个完全使用C语言编写的人工智能框架,可以使用CUDA的开源框架。主要应用于图像识别领域。 它具有可移植性好,安装间接,查看源码方便等优势,提供了OpenCV等附加选项,还…

(七)Pandas时序数据 学习简要笔记 #Python #CDA学习打卡

一. 时序数据简介 1)定义 时间序列(time series),就是由时间构成的序列,它指的是在一定时间内按照时间顺序测量的某个变量的取值序列,比如一天内的温度会随时间而发生变化,或者股票的价格会随…

c语言题目之求最大公约数

题目内容:求最大公约数 给定两个数,求这两个数的最大公约数 例如: 输入:20 40 输出:20 什么叫最大公约数? 方法分析: 提示:这里我们用辗转相除法: 例如:输…

Linux为根目录扩容

只适用于同一块硬盘扩容 背景:一块硬盘512G,双系统,window分了200G,同样也暂时给了linux 200G,随着使用linux不满足于这200,欲将剩下加其上 └─$ df -h # 查看已分配磁盘使用情况 Filesystem Size…