代码随想录算法训练营第十四天|递归 226.翻转二叉树 101. 对称二叉树 104.二叉树的最大深度 111.二叉树的最小深度

news2024/12/27 12:08:56


226.翻转二叉树

翻转一棵二叉树。

226.翻转二叉树

思路:

在这里需要注意的是,在递归的时候唯独中序遍历是不可用的,这是因为先对左子树进行了反转,又对自身进行了反转,对自身反转后原本的左子树变成了右子树,如果此时又轮到对右子树进行翻转,相当于原本的右子树没操作而对原来的左子树进行了两次翻转。

所以我们选择前序遍历,根据递归三部曲:

1.确定参数和返回值:参数是节点,而返回值可以是返回根节点,但我个人在一开始做的时候人为自定义了一个新的函数来专门对二叉树进行反转,是直接对二叉树进行操作的,所以认为不需要返回值,选择void或者->None

2.确定终止条件:当左孩子和右孩子都不存在的时候说明此时翻转无意义,此时return。(但规范写法的思路是当节点为空的时候return,我想这是因为如果只有一个左(右)孩子的时候依然会调用函数,这个时候有一个孩子节点是为空的,所以此时在定义递归函数的时候肯定还是需要定义一个条件:当节点为空时return,自然就不需要我一开始设置的这个条件了)

3.单层递归的逻辑:我选择最好理解的前序遍历,逻辑就是先对本节点进行操作,即对本节点的左右孩子进行互换,然后对左子树(左孩子节点)进行反转操作(调用递归),再对右子树进行反转操作。

根据以上思路,实现代码如下:

# Definition for a binary tree node.

# class TreeNode:

#     def __init__(self, val=0, left=None, right=None):

#         self.val = val

#         self.left = left

#         self.right = right

class Solution:

    def reverseTree(self, node: Optional[TreeNode]) -> None:

        if not node:

            return

        if not node.left and not node.right:

            return

       

        node.left, node.right = node.right, node.left

        self.reverseTree(node.left)

        self.reverseTree(node.right)

       



    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:

        if not root:

            return root

        self.reverseTree(root)

        return root

附上规范写法,更简洁和有效,应该学习:

# Definition for a binary tree node.

# class TreeNode:

#     def __init__(self, val=0, left=None, right=None):

#         self.val = val

#         self.left = left

#         self.right = right

class Solution:

    def invertTree(self, root: TreeNode) -> TreeNode:

        if not root:

            return None

        root.left, root.right = root.right, root.left

        self.invertTree(root.left)

        self.invertTree(root.right)

        return root

以上是递归写法,自然还能用迭代的方法,个人更喜欢使用广度优先(层序遍历),非常好理解,思路就是层序遍历压入队列中,然后依次进行反转,代码实现如下:

# Definition for a binary tree node.

# class TreeNode:

#     def __init__(self, val=0, left=None, right=None):

#         self.val = val

#         self.left = left

#         self.right = right

class Solution:

    def invertTree(self, root: TreeNode) -> TreeNode:

        if not root:

            return root

        queue = deque([root])

        while(queue):

            for _ in range(len(queue)):

                cur = queue.popleft()

                if cur.left:

                    queue.append(cur.left)

                if cur.right:

                    queue.append(cur.right)

                cur.left, cur.right = cur.right, cur.left

        return root

101. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

101. 对称二叉树

思路:

第一反应还是层序遍历,只需要将包括None的每一层节点数组都压入数组中,如果将数组的每一层数组反序输出与原数组都相同,那么说明是对称的。

但还是以学习递归为主,先优先实现递归的方法,思路是在每一个递归过程中,判断【孩子的孩子】和【孩子的孩子】是否相等,以及判断【孩子的孩子】和【孩子的孩子】是否相等。代码随想录将其分别称为外侧和里侧,可能更好理解一点。除了以上还需要确保根节点的左右孩子相等才行。

递归三部曲:

  1. 参数和返回值:参数为两个,是左右孩子两个节点,即要进行比较的两个子树根节点。返回值应该是bool,当出现任意一个false都应该返回false。
  2. 终止条件:①左空右不空->false ②左不空右空->false ③左右为空->True ④左右不空但数值不等->false
  3. 递归逻辑:当左右不空且数值相等时(这里其实是⑤,所以上面④的时候不能用else,只能用else if或者elif),才进入递归逻辑:判断【孩子的孩子】和【孩子的孩子】是否相等,只有当两个条件都符合时返回True,否则返回false。

代码实现如下:

# Definition for a binary tree node.

# class TreeNode:

#     def __init__(self, val=0, left=None, right=None):

#         self.val = val

#         self.left = left

#         self.right = right

class Solution:

    def compare(self, node1: Optional[TreeNode], node2: Optional[TreeNode]) -> bool:

        if node1 and not node2:

            return False

        elif not node1 and node2:

            return False

        elif not node1 and not node2:

            return True

        elif node1.val != node2.val:

            return False



        bool1 = self.compare(node1.left, node2.right)

        bool2 = self.compare(node1.right, node2.left)

        return bool1 and bool2



    def isSymmetric(self, root: Optional[TreeNode]) -> bool:

        if not root:

            return True

        if not root.left and not root.right:

            return True



        return self.compare(root.left, root.right)

规范代码:

class Solution:

    def isSymmetric(self, root: TreeNode) -> bool:

        if not root:

            return True

        return self.compare(root.left, root.right)

        

    def compare(self, left, right):

        #首先排除空节点的情况

        if left == None and right != None: return False

        elif left != None and right == None: return False

        elif left == None and right == None: return True

        #排除了空节点,再排除数值不相同的情况

        elif left.val != right.val: return False

        

        #此时就是:左右节点都不为空,且数值相同的情况

        #此时才做递归,做下一层的判断

        outside = self.compare(left.left, right.right) #左子树:左、 右子树:右

        inside = self.compare(left.right, right.left) #左子树:右、 右子树:左

        isSame = outside and inside #左子树:中、 右子树:中 (逻辑处理)

        return isSame

层序遍历:

# Definition for a binary tree node.

# class TreeNode:

#     def __init__(self, val=0, left=None, right=None):

#         self.val = val

#         self.left = left

#         self.right = right

class Solution:

    def isSymmetric(self, root: Optional[TreeNode]) -> bool:

        if not root:

            return True

       

        res = []

        queue = deque([root])

        while queue:

            arr = []

            for _ in range(len(queue)):

                cur = queue.popleft()

                if not cur:

                    arr.append(None)

                    continue

                arr.append(cur.val)

                queue.append(cur.left)

                queue.append(cur.right)

            res.append(arr)

        for arr in res:

            if arr != arr[::-1]:

                return False

        return True

规范代码(层序遍历):

class Solution:

    def isSymmetric(self, root: TreeNode) -> bool:

        if not root:

            return True

        

        queue = collections.deque([root.left, root.right])

        

        while queue:

            level_size = len(queue)

            

            if level_size % 2 != 0:

                return False

            

            level_vals = []

            for i in range(level_size):

                node = queue.popleft()

                if node:

                    level_vals.append(node.val)

                    queue.append(node.left)

                    queue.append(node.right)

                else:

                    level_vals.append(None)

                    

            if level_vals != level_vals[::-1]:

                return False

            

        return True

104.二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例: 给定二叉树 [3,9,20,null,null,15,7],

104. 二叉树的最大深度

返回它的最大深度 3 。

思路:

依然第一反应是层序遍历:每到新一层就更新最大值,最后返回最大值即可。

还是以学习递归为主,递归思路:

节点的深度是孩子节点的深度+1,那么只需要递归计算孩子节点的深度然后+1即可。

递归三部曲:

  1. 参数和返回值:参数应该是传入一个节点。返回值是传入节点的两个孩子节点的深度的最大值,应该是int类型。
  2. 终止条件:当左右孩子都不存在的时候,说明是叶子节点,此时返回深度1。当本节点不存在的时候,这时候为了区别于叶子节点,返回深度0
  3. 递归逻辑:对两个左右孩子进行递归调用,得到两个数值中的最大值然后再+1就可以得到当前节点的深度。

代码实现如下:

# Definition for a binary tree node.

# class TreeNode:

#     def __init__(self, val=0, left=None, right=None):

#         self.val = val

#         self.left = left

#         self.right = right

class Solution:

    def getdepth(self, node: Optional[TreeNode]) -> int:

        if not node:

            return 0

        if not node.left and not node.right:

            return 1

       

        return max(self.getdepth(node.left), self.getdepth(node.right)) + 1



    def maxDepth(self, root: Optional[TreeNode]) -> int:

        if not root:

            return 0

        return self.getdepth(root)

层序遍历:

# Definition for a binary tree node.

# class TreeNode:

#     def __init__(self, val=0, left=None, right=None):

#         self.val = val

#         self.left = left

#         self.right = right

class Solution:

    def maxDepth(self, root: Optional[TreeNode]) -> int:

        if not root:

            return 0

        queue = deque([root])

        res = 0

        while queue:

            for _ in range(len(queue)):

                cur = queue.popleft()      

                if cur.left:

                    queue.append(cur.left)

                if cur.right:

                    queue.append(cur.right)

            res += 1

        return res


111.二叉树的最小深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

111.二叉树的最小深度1

返回它的最小深度 2.

思路:

层序遍历思路:每层遍历记录层数,当第一次遍历到叶子节点的时候直接返回深度即可。

递归思路:与前面计算最大深度相似,但是需要注意的是,有一种情况不一样,也就是只有一个孩子的情况,因为没有孩子的情况有可能会返回0,但此时本节点并非叶子节点,此时如果空节点返回了深度0,那么此时计算到的最小深度是错误的。所以该题应该在遇到空孩子的时候直接跳过。

递归三部曲:

  1. 参数和返回值:参数是进入递归调用的节点。返回值应该是int类型的深度值。
  2. 终止条件:当左右孩子都不存在时(为叶子节点),返回深度1
  3. 递归逻辑:当左右孩子均存在时,计算两个孩子节点的深度的最小值,得到后+1作为返回值。如果只存在一个孩子,则计算存在的孩子节点的深度,然后+1作为返回值。、

代码实现如下:

# Definition for a binary tree node.

# class TreeNode:

#     def __init__(self, val=0, left=None, right=None):

#         self.val = val

#         self.left = left

#         self.right = right

class Solution:

    def minDepth(self, root: Optional[TreeNode]) -> int:

        return self.getdepth(root)



    def getdepth(self, node: Optional[TreeNode]) -> int:

        if not node:

            return 0

        if not node.left and not node.right:

            return 1

       

        if node.left and node.right:

            return min(self.getdepth(node.left), self.getdepth(node.right)) + 1

        elif not node.left and node.right:

            return self.getdepth(node.right) + 1

        elif node.left and not node.right:

            return self.getdepth(node.left) + 1

规范代码:

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)

层序遍历:

# Definition for a binary tree node.

# class TreeNode:

#     def __init__(self, val=0, left=None, right=None):

#         self.val = val

#         self.left = left

#         self.right = right

class Solution:

    def minDepth(self, root: Optional[TreeNode]) -> int:

        if not root:

            return 0

        queue = deque([root])

        res = 0

        while queue:

            for _ in range(len(queue)):

                cur = queue.popleft()      

                if cur.left:

                    queue.append(cur.left)

                if cur.right:

                    queue.append(cur.right)

                if not cur.left and not cur.right:

                    return res+1

            res += 1

        return res

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

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

相关文章

npm依赖安装的时候vue版本号报错处理

以下报错显示vue版本不对,需要改成这个版本"vue": "2.6.14"对应的版本 先看一下package.json中vue版本是多少 解决: npm install vue2.6.14

【重要提示】由于找不到msvcr110.dll 无法继续执行的解决途径全面解析

在使用Windows操作系统时,您可能会遇到这样的问题:某些应用程序在启动时提示“由于找不到 msvcr110.dll,无法继续执行代码。重新安装程序可能会解决此问题。” 这种错误通常会导致应用程序无法正常运行,影响用户体验。本文将全面介…

django开发流程1

一、官方网站: Django documentation | Django documentation | Djangohttps://docs.djangoproject.com/en/5.1/ 1.安装 django : pip install django 2. django项目的配置文件 (settings.py) BASE_DIR 项目根路径 DEBUG 调试模式 INSTALLE…

如何在算家云搭建CodeFormer(照片修复)

一、CodeFormer简介 CodeFormer 是一款强大的人工智能工具,专为处理低质量、损坏或模糊的面部图像而设计,主要用于图像和视频的修复和增强。它基于深度学习技术,通过先进的生成对抗网络(GAN)和自监督学习技术&#xf…

【LeetCode热题100】模拟

这篇博客记录了模拟相关的题目&#xff0c;也就是按照题目的描述写代码&#xff0c;很锻炼代码实现能力&#xff0c;包括了替换所有的问号、Z字形变换、外观数列、数青蛙4道题。 class Solution { public:string modifyString(string s) {int n s.size();for(int i 0 ; i <…

《数据结构与算法之美》学习笔记五之队列

前情提要&#xff1a;上一章学习了栈相关的知识&#xff0c;主要有下面的内容&#xff1a; 栈操作的时间复杂度&#xff0c;对于顺序栈&#xff0c;入栈时如果栈的空间不够涉及到数据搬移&#xff0c;此时使用摊还分析法&#xff0c;将数据搬移的耗时均摊到不需要搬移数据的入…

DeFi强势回归:新一轮DeFi牛市即将到来?

自2020年夏天的“DeFi之夏”以来&#xff0c;去中心化金融&#xff08;DeFi&#xff09;一直是加密行业的关键组成部分。“DeFi之夏”不仅将去中心化金融概念带入了实践&#xff0c;而且极大地推动了DeFi协议和应用的爆发式增长。尽管之后的市场经历了周期性的调整&#xff0c;…

【C++类的设计】题目(二):设计圆柱Column类

题目&#xff1a;设一个用于处理圆柱体的类Column&#xff0c;要求如下 (1)类中包含成员有&#xff1a;表示圆柱体底面半径的私有数据成员r&#xff0c;表示圆柱体高的私有数据成员h&#xff1b;构造对象时为私有数据成员赋值的构造函数&#xff0c;用于计算圆柱体表面积的函数…

OpenFeign使用详解

什么是OpenFeign&#xff1f; OpenFeign 是一个声明式的 HTTP 客户端&#xff0c;旨在简化微服务架构中不同服务之间的 HTTP 调用。它通过集成 Ribbon 实现了客户端负载均衡&#xff0c;并且能够与 Eureka、Consul 等服务发现组件无缝对接。使用 OpenFeign&#xff0c;开发者只…

如何使用ssm实现基于java web的防疫工作志愿者服务平台的设计与实现

TOC ssm693基于java web的防疫工作志愿者服务平台的设计与实现jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进…

Focalboard开源项目管理系统本地Windows部署与远程访问协同办公

文章目录 前言1. 使用Docker本地部署Focalboard1.1 在Windows中安装 Docker1.2 使用Docker部署Focalboard 2. 安装Cpolar内网穿透工具3. 实现公网访问Focalboard4. 固定Focalboard公网地址 &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&am…

Redis 篇-深入了解在 Linux 的 Redis 网络模型结构及其流程(阻塞 IO、非阻塞 IO、IO 多路复用、异步 IO、信号驱动 IO)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 用户空间与内核空间概述 2.0 Redis 网络模型 2.1 Redis 网络模型 - 阻塞 IO 2.2 Redis 网络模型 - 非阻塞 IO 2.3 Redis 网络模型 - IO 多路复用 2.3.1 IO 多路复…

vscode【实用插件】Markdown Preview Enhanced 预览 .md 文件

安装 在 vscode 插件市场的搜索 Markdown Preview Enhanced点安装 使用 用 vscode 打开任意 .md 文件右键快捷菜单 最终效果 可打开导航目录

liunxcentos7下 跟目录空间不足docker load镜像报错空间不足

前两天在公司&#xff0c;做jenkins流水线项目&#xff0c;然后把项目放到docker容器里面运行&#xff0c;就在我把镜像打好包的时候正准备往服务器里面导入镜像的时候报错&#xff1a;如图所示 这时发现自己的根目录空间不足。 解决办法&#xff1a;重新加一块磁盘将磁盘挂载…

Qemu开发ARM篇-5、buildroot制作根文件系统并挂载启动

文章目录 1、 buildroot源码获取2、buildroot配置3、buildroot编译4、挂载根文件系统 在上一篇 Qemu开发ARM篇-4、kernel交叉编译运行演示中&#xff0c;我们编译了kernel&#xff0c;并在qemu上进行了运行&#xff0c;但到最后&#xff0c;在挂载根文件系统时候&#xff0c;挂…

基于 Redis 实现滑动窗口的限流

⏳ 限流场景&#xff1a;突发流量&#xff0c;恶意流量&#xff0c;业务本身需要 基于 Redis 实现滑动窗口的限流是一种常见且高效的做法。Redis 是一种内存数据库&#xff0c;具有高性能和支持原子操作的特点&#xff0c;非常适合用来实现限流功能。下面是一个使用 Redis 实现…

谷歌浏览器如何把常用的网址创建快捷方式到电脑桌面?

1、打开想要创建快捷方式的网页之后&#xff0c;点击谷歌浏览器右上角的【三个点】 2、选择【保存并分享】&#xff0c;再选择【创建快捷方式】 3、之后在浏览器上方弹出的框中&#xff0c;重新命名快捷方式。 然后&#xff0c;点击【创建】 4、之后&#xff0c;即可在电…

手机解压软件加密指南:让文件更安全

在数字化时代&#xff0c;文件加密对于保护个人隐私和敏感信息的重要性不言而喻。随着互联网的飞速发展&#xff0c;我们的生活和工作越来越依赖于数字设备和网络。 然而&#xff0c;这也带来了一系列的安全风险&#xff0c;如黑客攻击、数据泄露等。文件加密技术成为了保护我…

mac m1 electron生产环境使用prisma,sqlite

最近在用electron开发一个适合自己的小应用&#xff0c;技术选型中使用prisma和sqlite在进行数据存储&#xff0c;写这篇文章的目的就是用来记录下遇到的一些问题。 开发环境使用prisma 1、开发环境使用prisma非常的简单&#xff0c;只需要按照教程安装prisma&#xff0c;然后…