代码随想录训练营 Day14打卡 二叉树 part02 226.翻转二叉树 101. 对称二叉树 104. 二叉树的最大深度 111. 二叉树的最小深度

news2025/1/12 12:16:03

代码随想录训练营 Day14打卡 二叉树 part02

一、 力扣226. 翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
示例 :
在这里插入图片描述
输入: root = [4,2,7,1,3,6,9]
输出: [4,7,2,9,6,3,1]

我们下文以前序遍历为例,通过动画来看一下翻转的过程:
在这里插入图片描述

版本一 递归法 前序遍历

思路:前序遍历的递归方法首先交换当前节点的左右子节点,然后递归地翻转左右子树。这是最直接的方法,因为它先处理当前节点,再递归处理子节点。

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

版本二 迭代法 前序遍历

思路:迭代使用栈来模拟递归的前序遍历。首先将根节点放入栈中,然后在每次从栈中取出一个节点时,交换它的左右子节点,并将子节点按右左顺序推入栈中。

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None      
        stack = [root]        
        while stack:
            node = stack.pop()
            node.left, node.right = node.right, node.left
            if node.left:
                stack.append(node.left)
            if node.right:
                stack.append(node.right)  
        return root

版本三 递归法 中序遍历

思路:中序遍历的递归方法与前序类似,但它在翻转左子树后交换左右子树,然后再递归翻转新的左子树(原右子树)。

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None
        # 先递归处理左子树
        self.invertTree(root.left)
        # 交换左右子树
        root.left, root.right = root.right, root.left
        # 注意这里需要再次递归处理新的左子树(原来的右子树)
        self.invertTree(root.left)
        return root

版本四 迭代法 中序遍历

思路:后序遍历的递归方法先处理所有子节点,然后再处理当前节点,即先翻转所有子树,然后交换左右子树。

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None      
        stack = []
        current = root
        while stack or current:
            while current:
                stack.append(current)
                current = current.left
            current = stack.pop()
            # 交换操作
            current.left, current.right = current.right, current.left
            # 处理右子树
            current = current.left
        return root

版本五 迭代法 后序遍历

思路:迭代的后序遍历使用栈来先处理所有子节点,然后在从栈中取出节点时进行交换。

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return None      
        stack = [root]        
        while stack:
            node = stack.pop()                   
            if node.left:
                stack.append(node.left)
            if node.right:
                stack.append(node.right)  
            node.left, node.right = node.right, node.left               
     
        return root

版本六 迭代法 广度优先遍历(层序遍历)

思路:层序遍历使用队列来逐层交换节点的左右子节点。每次从队列中取出一个节点时交换其子节点,然后将子节点加入队列中。

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        # 如果根节点为空,则直接返回None
        if not root: 
            return None

        # 使用队列来进行层序遍历,初始时队列中只有根节点
        queue = collections.deque([root])    
        while queue:
            # 处理当前层的所有节点
            for i in range(len(queue)):
                # 从队列中弹出当前节点
                node = queue.popleft()
                # 交换当前节点的左右子节点
                node.left, node.right = node.right, node.left
                # 如果左子节点存在,将其加入队列
                if node.left: 
                    queue.append(node.left)
                # 如果右子节点存在,将其加入队列
                if node.right: 
                    queue.append(node.right)
        return root   

力扣题目链接
题目文章讲解
题目视频讲解

二、 力扣101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。
示例 :
在这里插入图片描述
输入: root = [1,2,2,3,4,4,3]
输出: true

对于二叉树是否对称,要比较的是根节点的左子树与右子树是不是相互翻转的,理解这一点就知道了其实我们要比较的是两个树(这两个树是根节点的左右子树),所以在递归遍历的过程中,也是要同时遍历两棵树。

那么如何比较呢?

比较的是两个子树的里侧和外侧的元素是否相等。如图所示:
在这里插入图片描述
那么遍历的顺序应该是什么样的呢?

本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。

正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。

但都可以理解算是后序遍历,尽管已经不是严格上在一个树上进行遍历的后序遍历了。

实现思路:

  1. 定义递归函数: 递归函数接收两个节点作为参数,分别为来自两棵子树的对应节点。
  2. 递归终止条件: 如果两个节点都为空,返回 True;如果一个为空另一个不为空,或者两个节点的值不相同,返回 False。
  3. 递归比较逻辑: 递归比较一个节点的左子节点与另一个节点的右子节点,以及一个节点的右子节点与另一个节点的左子节点。

版本一 递归法

实现思路:这种方法通过递归判断每一层的对称性,确保树的每一层都是对称的。首先排除空节点的情况,然后再递归比较外侧和内侧节点。

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)  # 左子树的右节点和右子树的左节点
        return outside and inside  # 两者都需要为真,整体才对称

版本二 迭代法 使用队列

实现思路:使用队列实现层序遍历,同时比较两个节点,以确保它们是对称的。每次从队列中取两个节点进行比较,然后按相应的对称顺序将它们的子节点加入队列。

import collections
class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True  # 如果根节点为空,树自然对称
        queue = collections.deque()
        # 初始化队列,加入根节点的左右子节点
        queue.append(root.left)
        queue.append(root.right)
        while queue:
            leftNode = queue.popleft()
            rightNode = queue.popleft()
            # 如果左右节点同时为空,对称,继续循环
            if not leftNode and not rightNode:
                continue
            # 如果一个为空另一个不为空,或值不同,则不对称
            if not leftNode or not rightNode or leftNode.val != rightNode.val:
                return False
            # 将子节点按对称位置加入队列
            queue.append(leftNode.left)
            queue.append(rightNode.right)
            queue.append(leftNode.right)
            queue.append(rightNode.left)
        return True
        

版本三 迭代法 使用栈

实现思路:类似于使用队列的方法,但这里使用栈来存储节点。这种方法同样需要成对地取出节点进行比较,并将子节点按对称顺序推入栈中。

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True  # 如果根节点为空,树自然对称
        st = []  # 使用栈来存储节点
        st.append(root.left)
        st.append(root.right)
        while st:
            rightNode = st.pop()
            leftNode = st.pop()
            # 如果左右节点同时为空,对称,继续循环
            if not leftNode and not rightNode:
                continue
            # 如果一个为空另一个不为空,或值不同,则不对称
            if not leftNode or not rightNode or leftNode.val != rightNode.val:
                return False
            # 将子节点按对称位置加入栈
            st.append(leftNode.left)
            st.append(rightNode.right)
            st.append(leftNode.right)
            st.append(rightNode.left)
        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. 二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
在这里插入图片描述
示例 :
输入: root = [3,9,20,null,null,15,7]
输出: 3

版本一 递归法

实现思路:通过递归的方式,自底向上计算每个节点的最大深度,直到根节点。这种方法利用了树的后序遍历(左右中)的特点。

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        # 调用辅助函数来递归地求深度
        return self.getDepth(root)
        
    def getDepth(self, node):
        # 如果节点为空,深度为0
        if not node:
            return 0
        # 递归求左子树的深度
        leftHeight = self.getDepth(node.left)
        # 递归求右子树的深度
        rightHeight = self.getDepth(node.right)
        # 当前节点的深度是左右子树深度的最大值加1(加的1是当前节点这一层)
        height = 1 + max(leftHeight, rightHeight)
        return height

版本二 递归法 精简代码

实现思路:这是递归法的一个更简洁的版本,直接在返回时计算深度。它避免了使用额外的辅助函数,但本质上与第一个递归方法相同。

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        # 如果根节点为空,返回深度0
        if not root:
            return 0
        # 递归地计算左右子树的深度,并取最大值,然后加1代表当前层的深度
        return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right))

版本三 层序遍历迭代法

实现思路:通过层序遍历(广度优先遍历)计算树的深度。这种方法使用队列存储每一层的所有节点,每处理完一层,深度计数器加1。这个方法非常适合迭代地处理树的层级结构。

import collections

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0  # 如果树为空,深度为0
        
        depth = 0  # 初始化深度为0
        queue = collections.deque([root])  # 使用队列存储每一层的节点
        
        while queue:
            depth += 1  # 每遍历一层,深度加1
            for _ in range(len(queue)):  # 遍历当前层的所有节点
                node = queue.popleft()  # 取出节点
                if node.left:  # 如果有左子节点,加入队列
                    queue.append(node.left)
                if node.right:  # 如果有右子节点,加入队列
                    queue.append(node.right)
        
        return depth  # 遍历结束后返回深度

力扣题目链接
题目文章讲解
题目视频讲解

四、 力扣111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
示例 :
在这里插入图片描述
输入: root = [3,9,20,null,null,15,7]
输出: 2

本题有一个误区,在处理节点的过程中,最大深度很容易理解,最小深度就不那么好理解,如图:
在这里插入图片描述
这就重新审题了,题目中说的是:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。注意是叶子节点。

什么是叶子节点,左右孩子都为空的节点才是叶子节点!

版本一 递归法

实现思路:此方法递归地计算左右子树的深度,并在存在子树时考虑只有单侧子树的情况,确保只计算到叶子节点的深度。

class Solution:
    def getDepth(self, node):
        if node is None:
            return 0  # 空节点的深度为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)

版本二 递归法 前序

实现思路:这种方法维护一个类成员变量 result 存储最小深度,通过前序遍历逐节点检查更新最小值。

class Solution:
    def __init__(self):
        self.result = float('inf')  # 初始化最小深度为无穷大

    def getDepth(self, node, depth):
        if node is None:
            return
        if node.left is None and node.right is None:
            # 更新最小深度
            self.result = min(self.result, depth)
        # 递归访问左子树
        if node.left:
            self.getDepth(node.left, depth + 1)
        # 递归访问右子树
        if node.right:
            self.getDepth(node.right, depth + 1)

    def minDepth(self, root):
        if root is None:
            return 0
        self.getDepth(root, 1)
        return self.result

版本三 迭代法

实现思路:使用队列进行层序遍历,每遍历完一层深度加一。当遇到第一个叶子节点时,返回当前深度。

import collections

class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:
            return 0  # 空树的深度为0
        depth = 0
        queue = collections.deque([root])  # 使用队列进行层序遍历
        
        while queue:
            depth += 1  # 层次深度
            for _ in range(len(queue)):  # 处理当前层的所有节点
                node = queue.popleft()
                
                # 检查是否到达叶子节点
                if not node.left and not node.right:
                    return depth
            
                # 将子节点加入队列
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)

        return depth

力扣题目链接
题目文章讲解
题目视频讲解

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

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

相关文章

前端工程化-vue项目创建

可以使用html、css、javascpript ,以及使用vue、axios等技术搭建前端页面,但效率低、结构乱。 实际前端开发: 前端工程化开发步骤: 一、环境准备 1.安装NodeJS2. 安装vue-cli 二、创建Vue项目 有两种方式创建,一般采用第二种图…

【连续3年稳定发表,门槛低 易中稿】第四届先进制造技术与电子信息国际学术会议(AMTEI 2024,9月20-22)

由深圳技术大学集成电路与光电芯片学院、中南大学自动化学院联合支持的第四届先进制造技术与电子信息学术会议(AMTEI 2024)将于2024年09月20-22日在重庆召开。 本次会议主要围绕先进制造技术与电子信息的最新研究领域,为来自国内外高等院校、…

Springboot+Thymeleaf实现纯静态化页面处理

前言&#xff1a;引入包什么的就不讲了&#xff0c;这里我只记录如何实现。 在template目录下构建模板页面 IndexTemplate.html。一般模板文件都是放在这个下面<!DOCTYPE html> <html lang"zh" xmlns:th"http://www.thymeleaf.org"> <head&…

深度模型中的优化 - 优化策略和元算法篇

序言 在人工智能与机器学习的快速发展中&#xff0c;深度模型作为核心技术之一&#xff0c;其优化问题至关重要。深度模型通过构建多层神经网络来模拟人脑的学习与推理过程&#xff0c;处理复杂数据模式与任务。然而&#xff0c;这些强大能力的背后&#xff0c;离不开高效的优…

【python函数】调用系统命令进行文件夹的创建与删除

大家好&#xff0c;我是一名_全栈_测试开发工程师&#xff0c;已经开源一套【自动化测试框架】和【测试管理平台】&#xff0c;欢迎大家关注我&#xff0c;和我一起【分享测试知识&#xff0c;交流测试技术&#xff0c;趣聊行业热点】。 一、函数说明&#xff1a; 获取系统名称…

人工智能计算机视觉系列—构建你的图像标签管理系统:使用Flask和SQLite实现前后端应用

文章目录 1. 项目背景2. 方案概述3. 环境部署4. 具体实现5. 运行步骤6. 总结 1. 项目背景 在机器学习和计算机视觉的开发过程中&#xff0c;我们经常需要处理大量的图像及其标签信息。一个直观、便捷的图像和标签展示工具可以极大地提高开发效率。本文将介绍如何使用Flask框架…

最靠谱的搭建方式-ESP32入门搭建Arduino开发环境基于mac系统

ESP32入门搭建Arduino开发环境基于mac系统 1.概述 ESP32开发版作为物联网开发非常的方便&#xff0c;不过在入门时候搭建Arduino开发环境比较麻烦&#xff0c;因为Arduino在下载ESP32开发环境时总是失败&#xff0c;因此不得不采用手动安装环境方式。 这篇文章主要介绍mac系统…

Java 并发编程实战权威指南(电子版教程)

前言 Java并发编程主要涉及多线程编程&#xff0c;通过创建多个线程来并发执行任务&#xff0c;从而提高程序的执行效率和响应能力。Java提供了多种机制和技术来实现并发编程&#xff0c;包括进程和线程的管理、同步机制、高级并发工具以及最佳实践。 一、下载地址 下载地址…

hadoop学习笔记3-yarn

4.YARN yarn本质上是一个负责管理资源节点、调度资源节点的资源调度平台&#xff0c;负责为运算程序提供服务器计算资源&#xff0c;把任务调度到合适的节点上执行 4.1yarn架构 yarn 主要由ResourceManager、NodeManager、applicationmaster组件构成 yarn将资源管理和应用程…

PowerDNS架构解析与安装部署指南

1、背景介绍 目前公司使用PowerDNS进行DNS管理&#xff0c;但由于采用的是单节点架构&#xff0c;存在不可用的风险。为提升系统的稳定性和可靠性&#xff0c;我们计划对现有架构进行重构。通过引入高可用性设计&#xff0c;我们将优化系统架构&#xff0c;使其能够在故障情况…

设计模式 之 —— 抽象工厂模式

目录 什么是抽象工厂模式&#xff1f; 定义 特点 抽象工厂模式&#xff08;java代码示例&#xff09; 首先定义第一个接口 实现第一个接口的类 定义第二个接口 实现第二个接口的类 * 创建抽象工厂类 创建扩展了 AbstractFactory 的工厂类 饮料工厂 食物工厂 * 创建一个…

非科班出身的你,如何转行web安全工程师?零基础入门到精通,收藏这一篇就够了

想从其他行业转行到算法工程师的人&#xff0c;无外乎以下几个原因&#xff1a; 现在工资太低 工作没有前景 对现在的工作没有热情 对web安全工程师很感兴趣 那么&#xff0c;转行web安全工程师&#xff0c;你需要掌握哪些技能呢&#xff1f; ​ 为了帮助大家更好的学习网络…

第100+18步 ChatGPT学习:R实现SVM分类

基于R 4.2.2版本演示 一、写在前面 有不少大佬问做机器学习分类能不能用R语言&#xff0c;不想学Python咯。 答曰&#xff1a;可&#xff01;用GPT或者Kimi转一下就得了呗。 加上最近也没啥内容写了&#xff0c;就帮各位搬运一下吧。 二、R代码实现SVM分类 &#xff08;1&a…

Docker部署nacos...用户名密码错误

前提 镜像选择v2.3.0版本&#xff0c;因为最新的没拉下来用的别的地方save load的镜像。 官方示例 官方文档 数据库脚本&#xff0c;直接去数据库新建数据库nacos吧&#xff0c;执行脚本&#xff0c;执行完成后&#xff0c;发现只有建表语句&#xff0c;查询得知&#xff0c…

springboot+Activiti7整合实践 (九) 网关

系列文章目录 第一章 springbootActiviti7整合实践 (一) 第二章 springbootActiviti7整合实践 (二) 模型定义 第三章 springbootActiviti7整合实践 (三) 流程定义 第四章 springbootActiviti7整合实践 (四) 分配规则 第五章 springbootActiviti7整合实践 (五) 发布流程 第…

股票预测模型中注意力多层Attention RNN LSTM 的应用

全文链接&#xff1a;https://tecdat.cn/?p37152 原文出处&#xff1a;拓端数据部落公众号 Attention 机制是一种在神经网络处理序列数据时极为关键的技术&#xff0c;它赋予了模型“聚焦”能力&#xff0c;能够自动评估输入序列中各部分的重要性。通过为序列中的每个元素分…

一文读懂CST电磁仿软件的TLM算法原理和历史背景

这期我们免公式地介绍一下TLM原理。TLM&#xff08;Transmission Line Method&#xff09;是传输线矩阵算法&#xff0c;基于Huygens的波传播模型的三维全波电磁算法&#xff0c;注意是full wave哦&#xff01; 什么是Huygens原理&#xff1f; 惠更斯原理能准确计算波的传播。…

三大旗舰实力,奇瑞风云T10全球上市,售价18.99万元起

旗舰之上&#xff0c;10力超群&#xff01;7月25日&#xff0c;超长续航旗舰电混SUV——风云T10于弥勒全球上市。基于全球标准及全球验证体系打造的风云T10&#xff0c;凭借旗舰级的性能、安全、空间三大产品价值&#xff0c;树立了新能源时代的新标杆。新车共推出3款车型&…

目标检测 YOLOv5-7.0 详细调试自制数据集实战

目标检测 YOLOv5-7.0 详细调试&自制数据集实战 一、项目介绍及环境配置&#xff08;一&#xff09;项目解读&#xff08;二&#xff09;版本选择&#xff08;三&#xff09;环境配置 二、如何利用YOLOv5进行预测&#xff08;detect.py&#xff09;&#xff08;一&#xff0…

DOS攻击实验

实验背景 Dos 攻击是指故意的攻击网络协议实现的缺陷或直接通过野蛮手段&#xff0c;残忍地耗尽被攻击对象的资源&#xff0c;目的是让目标计算机或网络无法提供正常的服务或资源访问&#xff0c;使目标系统服务系统停止响应甚至崩溃。 实验设备 一个网络 net:cloud0 一台模…