LeetCode226. 翻转二叉树

news2024/11/26 0:56:07

226. 翻转二叉树

文章目录

      • [226. 翻转二叉树](https://leetcode.cn/problems/invert-binary-tree/)
        • 一、题目
        • 二、题解
          • 方法一:层序遍历迭代
          • 方法二:前序遍历(递归)
          • 方法三:中序遍历(递归)
          • 方法四:后序遍历(递归)
          • 方法五:前序遍历(迭代)
          • 方法六:迭代统一写法


一、题目

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

在这里插入图片描述

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

示例 2:

在这里插入图片描述

输入:root = [2,1,3]
输出:[2,3,1]

示例 3:

输入:root = []
输出:[]

二、题解

方法一:层序遍历迭代

算法思路:

  1. 翻转一棵树,就是将树中所有节点的左右子节点进行交换。

  2. 可以采用广度优先搜索的方式遍历这棵树,依次翻转每个节点的左右子节点。

  3. 使用双端队列作为辅助存储结构,以队列的方式维护待遍历的节点。

具体实现:

  1. 定义双端队列deq,用于存储待遍历的节点。

  2. 从根节点开始,将根节点入队到deq。

  3. 开始遍历:

    • 记录当前队列大小size,用于控制每层遍历次数

    • 循环size次,每次队头出队一个节点:

      • 交换该节点的左右子节点指针

      • 如果左右子节点不为空,加入deq继续遍历(注意是先push右节点,然后push左节点)

  4. 遍历完成后,整棵树的节点都被翻转过

  5. 返回根节点

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == nullptr) return root;
        deque<TreeNode*> deq;
        deq.push_back(root);
        while(!deq.empty()){
            int size = deq.size();
            for(int i = 0; i < size; i++){
                TreeNode *node = deq.front();
                deq.pop_front();
                swap(node->left,node->right);
                /*TreeNode *temp = node->right;
                node->right = node->left;
                node->left = temp;*/
                if(node->right) deq.push_back(node->right);
                if(node->left) deq.push_back(node->left);
            }
        }
        return root;
    }
};

算法分析:

  • 时间复杂度 O(N):遍历了树中的所有节点

  • 空间复杂度 O(N):队列中最多存储树的所有节点

方法二:前序遍历(递归)

算法思路:

  1. 二叉树的翻转可以使用递归的方法实现。

  2. 思路是,对树的每个节点,交换它的左右子节点,然后递归地对它的左右子节点进行翻转。

  3. 通过递归,可以一层一层地进行节点交换,直到叶子节点,实现整棵树的翻转。

具体实现:

  1. 定义递归函数invertTree,输入根节点root。

  2. 在函数内:

    • 交换root的左右子节点

    • 递归调用invertTree,输入root的左子节点

    • 递归调用invertTree,输入root的右子节点

  3. 当递归到叶子节点时,左右子节点为空,直接返回。

  4. 通过递归返回,整棵树的节点都被交换过了。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == nullptr) return root;
        swap(root->left,root->right);
        invertTree(root->left);
        invertTree(root->right);
        return root;
    }
};

算法分析:

  • 时间复杂度 O(N):需要递归遍历树的所有节点。

  • 空间复杂度 O(H):递归函数在递归调用栈上需要O(H)空间,H为树高。

方法三:中序遍历(递归)

具体实现:

  1. 定义递归函数invertTree,输入根节点root。

  2. 在函数内:

    • 首先递归翻转左子树

    • 然后交换当前root节点的左右子树

    • 最后递归翻转右子树(已经交换后的左子树)

  3. 通过递归先序遍历的流程,每个节点都会被翻转一次。

  4. 当遍历到null时,直接返回,递归终止。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == nullptr) return root;
        
        invertTree(root->left);
        swap(root->left,root->right);
        invertTree(root->left);
        
        return root;
    }
};

算法分析:

  • 时间复杂度 O(N):遍历树的所有节点。

  • 空间复杂度 O(H):递归栈空间为树高。

方法四:后序遍历(递归)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if(root == nullptr) return root;
        
        invertTree(root->left);
        invertTree(root->right);
        swap(root->left,root->right);
        return root;
    }
};
方法五:前序遍历(迭代)
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> st;
        if(root == nullptr) return root;
        st.push(root);
        while(!st.empty()){
            TreeNode* node = st.top();
            st.pop();
            swap(node->left,node->right);
            if(node->right) st.push(node->right);
            if(node->left) st.push(node->left);
        }
        return root;
    }
};
方法六:迭代统一写法

前序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> st;
        if(root == nullptr) return root;
        st.push(root);
        while(!st.empty()){
            TreeNode* node = st.top();
            if(node != NULL){
                st.pop();
                if(node->right) st.push(node->right);	//右
                if(node->left) st.push(node->left);	//左
                st.push(node);	//中
                st.push(NULL);
            }else{
                st.pop();
                node = st.top();
                st.pop();
                swap(node->left,node->right);
            }
        }
        return root;
    }
};

中序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> st;
        if(root == nullptr) return root;
        st.push(root);
        while(!st.empty()){
            TreeNode* node = st.top();
            if(node != NULL){
                st.pop();
                if(node->right) st.push(node->right);	//右
                st.push(node);	//中
                st.push(NULL);
                if(node->left) st.push(node->left); //左
                
            }else{
                st.pop();
                node = st.top();
                st.pop();
                swap(node->left,node->right);
            }
        }
        return root;
    }
};

后序遍历

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        stack<TreeNode*> st;
        if(root == nullptr) return root;
        st.push(root);
        while(!st.empty()){
            TreeNode* node = st.top();
            if(node != NULL){
                st.pop();
                st.push(node);	//中
                st.push(NULL);
                if(node->right) st.push(node->right);   //右    
                if(node->left) st.push(node->left); //左
                
            }else{
                st.pop();
                node = st.top();
                st.pop();
                swap(node->left,node->right);
            }
        }
        return root;
    }
};

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

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

相关文章

c++ visual studio opencv配置

项目属性表配置方式&#xff1a; 1、新建项目后&#xff0c;在属性管理器中&#xff0c;创建一个项目属性表&#xff1a; 注&#xff1a;根据需求创建。 2、双击项目属性表 依次修改包含目录、库目录、附加包含目录、附加依赖项。 2.1【包含目录】中加入 OpenCV 的 include …

为harbor仓库添加https,新增DigiCert 免费版SSL证书

完成效果&#xff1a; 前言&#xff1a;在本地搭建好docker的镜像仓库harbor后&#xff0c;当我们登录docker login时&#xff0c;会提示证书问题x509: cannot validate certificate 登录本地报错X509 无法登录仓库也无法上传和拉取镜像&#xff0c;虽然有本机的解决方法&…

android studio 新建项目没有R文件

android studio 新建项目没有R文件&#xff0c;处理步骤 1&#xff0c;找一个能打开的项目替换根目录下的settings.gradle 2,改app 目录下的build.gradle文件 3&#xff0c;改gradle版本 4&#xff0c;改AndroidManifest.xml 5&#xff0c;改theme 改为&#xff0c;ok.

gtest测试用例注册及自动化调度机制源代码流程分析

gtest的入门参见&#xff1a; 玩转Google开源C单元测试框架Google Test系列(gtest) gtest源码分析流程参见&#xff1a; gtest流程解析 测试用例注册流程分析要点&#xff1a;TEST_F宏替换、C静态成员的动态初始化。 自动化调度流程分析要点&#xff1a;UnitTest、UnitTestIm…

CRM系统的排名?都有哪些特点?

在当今商业世界中&#xff0c;CRM客户管理系统是每一家企业所必不可少的工具。它们能够帮助企业管理客户信息&#xff0c;跟进销售机会以及提高客户体验。众多的CRM中&#xff0c;哪个CRM性价比高&#xff0c;企业该如何选择&#xff1f; 在比较CRM软件时&#xff0c;除基本功…

90道渗透测试面试题(附答案)

2023年已经快过去一半了&#xff0c;不知道小伙伴们有没有找到自己心仪的工作呀。最近后台收到不少小伙伴说要我整理一些渗透测试的面试题&#xff0c;今天它来了&#xff01;觉得对你有帮助的话记得点个赞再走哦~ 1、什么是渗透测试&#xff1f; 渗透测试是一种评估计算机系统…

HCIA练习2

目录 第一步 启动eNSP&#xff0c;搭建如图所示的拓扑结构 第二步 进行子网的划分 ​第三步 从第二步划分的16个网段中&#xff0c;选择14个网段进行使用 第四步 对路由器各个端口进行IP配置 第五步 对每个路由器的环回接口进行配置 第六步 对路由器进行静态路由配…

QT designer的安装+PyUIC 和 PyRCC

PyQt5的安装 整个环境的搭建&#xff0c;主要内容为&#xff1a;Python PyCharm PyQt5 学习pyqt5制作界面的视频推荐网址&#xff1a; https://www.bilibili.com/video/BV1YT4y1r7tK?spm_id_from333.999.0.0&vd_sourceda469f8dadbc58a00f885b3f7be5ef05 配置工具&…

java项目之文物管理系统(ssm+mysql+jsp)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的文物管理系统。技术交流和部署相关看文章末尾&#xff01; 开发环境&#xff1a; 后端&#xff1a; 开发语言&#xff1a;Java 框架&…

Linux系统上安装 Redis 5.0 版本

文章目录 一、安装 gcc二、Redis官网下载安装包三、xftp上传安装包四、解压安装包五、编译与安装&#xff08;make&#xff09;六、后台启动七、查看rdis进程八、客户端连接 一、安装 gcc 安装gcc的主要作用是提供编译器和工具链&#xff0c;因为redis是c语言编写的&#xff0…

基于Vue+Element Plus实现表格组件

目录 前言分析实现例子效果图前言 表格对于管理类项目是很重要的,可以只管的展示和比比较数据。使用Element Plus能解决一部分问题,但是还存在一些缺点和不足。 分析 浏览器上表格数据展示空间不足。列显示太多不够直观。完全依赖官方表格组件代码过于臃肿不利于管理和优化…

mybatis 基础3

1.collection标签 查询-场景&#xff1a;一对多 2.动态查询 3.动态添加 4.动态修改 5. 批量添加 foreach标签中属性的用法 6.查询-参数为List 7.查询-参数为Map

【后端面经】前言汇总(0)

文章目录 一、机会是留给有准备的人二、课程设计第一部分:微服务架构第二部分:数据库与 MySQL第三部分:消息队列第四部分:缓存所谓缓存用得好,性能没烦恼。第五部分:NoSQL三、总结一、机会是留给有准备的人 近两年互联网行业增速放缓,ChatGPT 又引发了一波新的 AI 浪潮,…

“百模大战”打响,如何评估一个AI大模型的能力水平?

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 大型AI模型已经变得越来越常见&#xff0c;它们在许多复杂任务中展现出了强大的实力&#xff0c;引领着前沿技术的发展趋势。这些大模型既给了我们无限的可能&#xff0c;也带来了一个难题&#xff1a;在“百模大战”的大背…

【Flume 01】Flume简介、部署、组件

1 Flume简介 Flume是一个高可用、高可靠、分布式的海量日志采集、聚合和传输的系统 主要特性&#xff1a; 它有一个简单、灵活的基于流的数据流结构&#xff08;使用Event封装&#xff09;具有负载均衡机制和故障转移机制一个简单可扩展的数据模型(Source、Channel、Sink) Sou…

C# List 详解一

目录 一、概述 二、构造函数 1.List() 2.List(IEnumerable) 3.List(Int32) 三、属性 1.Capacity 2.Count 3.Item[Int32] 四、方法 1.Add(T) 2.AddRange(IEnumerable) 3.AsReadOnly() 4.BinarySearch(T) C# List 详解一 1.Add…

vue3+antd搭建登录页面——vue3初体验——基础积累

最近在跟着大神学习vue3&#xff0c;学习过程中遇到各种问题&#xff0c;简直跟几年前学习vue2时一样的不知所措。 认识vite_vue3 初始化项目到打包&#xff1a;http://t.csdn.cn/B3bwC 为了方便&#xff0c;我是直接在stepin-template项目的基础上操作的&#xff0c;省略了上…

Unity VisualScripting(Bolt)自定义Node(带详细注释)

效果&#xff1a;获取一个物体的全部子物体和孙物体等从属物体 //引用一些东西&#xff0c;这样才能用某些API using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine;//类名和Node名一样 public class GetTreeChildr…

为什么要学框架?什么是Spring?

为什么要学框架&#xff1f;什么是Spring&#xff1f; 一、为什么要学框架&#xff1f; 学习框架相当于从 “小作坊” 到 “工厂” 的升级&#xff0c;小作坊什么都要自己做&#xff0c;工厂是组件式装配&#xff0c;特点就是高效。框架更加易用、简单且高效。 框架的优点展…

51单片机--DS18B20温度感应器

文章目录 DS18B20的介绍内部结构框图DS18B20存储器单总线的介绍硬件结构 单总线的时序结构温度存储格式DS18B20操作流程在LCD屏上显示温度实例 DS18B20的介绍 DS18B20是一种常用的数字温度传感器&#xff1b; 下面介绍它的特点和功能&#xff1a; 封装和引脚定义&#xff1a;…