LeetCode 226.翻转二叉树(全网最多的解法)

LeetCode 226.翻转二叉树

1、题目

题目链接:226. 翻转二叉树
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:
image.png

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

示例 2:
image.png

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

示例 3:

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

提示:

  • 树中节点数目范围在 [0, 100] 内
  • -100 <= Node.val <= 100

2、递归(前序遍历)

思路

我们从根节点开始翻转,先交换左右孩子节点,然后翻转左子树,最后翻转右子树。即可完成以 root 为根节点的整棵子树的翻转。

代码

#include <iostream>using namespace std;//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 nullptr;}// 交换左右子树swap(root->left, root->right);// 递归翻转左子树invertTree(root->left);// 递归翻转右子树invertTree(root->right);// 返回翻转后的根节点return root;}
};int main() {TreeNode* root = new TreeNode(4, new TreeNode(2, new TreeNode(1), new TreeNode(3)), new TreeNode(7, new TreeNode(6), new TreeNode(9)));Solution s;TreeNode* res = s.invertTree(root);cout << res->val << endl;cout << res->left->val << endl;cout << res->right->val << endl;cout << res->left->left->val << endl;cout << res->left->right->val << endl;cout << res->right->left->val << endl;cout << res->right->right->val << endl;delete root;return 0;
}

复杂度分析

  • 时间复杂度:O(N),其中 N 为二叉树节点的数目。我们会遍历二叉树中的每一个节点,对每个节点而言,我们在常数时间内交换其两棵子树。
  • 空间复杂度:O(N)。使用的空间由递归栈的深度决定,它等于当前节点在二叉树中的高度。在平均情况下,二叉树的高度与节点个数为对数关系,即 O(log⁡N)。而在最坏情况下,树形成链状,空间复杂度为 O(N)。

3、递归(中序遍历)

思路

注意:写中序遍历的时候,不能仅仅只是将前序遍历的代码顺序调整一下。
因为在“中序遍历”的时候,左右子树已经交换过了,因此原来写 invertTree(root.right); 的地方,应该写作 invertTree(root.left);

代码

class Solution {
public:TreeNode* invertTree(TreeNode* root) {// 如果根节点为空,则返回空指针if (root == nullptr) {return nullptr;}// 递归翻转左子树invertTree(root->left);// 交换左右子树swap(root->left, root->right);// 递归翻转右子树invertTree(root->left);// 返回反转后的根节点return root;}
};

复杂度分析

  • 时间复杂度:O(N),其中 N 为二叉树节点的数目。我们会遍历二叉树中的每一个节点,对每个节点而言,我们在常数时间内交换其两棵子树。
  • 空间复杂度:O(N)。使用的空间由递归栈的深度决定,它等于当前节点在二叉树中的高度。在平均情况下,二叉树的高度与节点个数为对数关系,即 O(log⁡N)。而在最坏情况下,树形成链状,空间复杂度为 O(N)。

4、递归(后序遍历)

思路

我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转。如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。

代码

class Solution {
public:TreeNode* invertTree(TreeNode* root) {// 如果根节点为空,则返回空指针if (root == nullptr) {return nullptr;}// 递归翻转左子树invertTree(root->left);// 递归翻转右子树invertTree(root->right);// 交换左右子树swap(root->left, root->right);// 返回反转后的根节点return root;}
};

复杂度分析

  • 时间复杂度:O(N),其中 N 为二叉树节点的数目。我们会遍历二叉树中的每一个节点,对每个节点而言,我们在常数时间内交换其两棵子树。
  • 空间复杂度:O(N)。使用的空间由递归栈的深度决定,它等于当前节点在二叉树中的高度。在平均情况下,二叉树的高度与节点个数为对数关系,即 O(log⁡N)。而在最坏情况下,树形成链状,空间复杂度为 O(N)。

5、迭代法(前序遍历)

代码

class Solution {
// 迭代法(前序遍历):使用栈,先将根节点入栈,然后不断弹出栈顶节点,交换其左右子树,并将右子树、左子树入栈,直到栈为空
public:TreeNode* invertTree(TreeNode* root) {// 如果根节点为空,则直接返回空if (root == nullptr) return nullptr;// 创建一个栈,用于存储待处理的节点stack<TreeNode*> stk;// 将根节点入栈stk.push(root);// 当栈不为空时,循环处理栈中的节点while(!stk.empty()) {// 取出栈顶节点TreeNode* node = stk.top();// 将栈顶节点出栈stk.pop();// 交换当前节点的左右子树swap(node->left, node->right);// 如果当前节点的右子树不为空,则将右子树入栈if(node->right) stk.push(node->right);// 如果当前节点的左子树不为空,则将左子树入栈if(node->left) stk.push(node->left);}// 返回根节点return root;}
};

复杂度分析

  • 时间复杂度:O(N),其中 N 为二叉树节点的数目。我们会遍历二叉树中的每一个节点,对每个节点而言,我们在常数时间内交换其两棵子树。
  • 空间复杂度:O(N)。使用的空间由递归栈的深度决定,它等于当前节点在二叉树中的高度。在平均情况下,二叉树的高度与节点个数为对数关系,即 O(log⁡N)。而在最坏情况下,树形成链状,空间复杂度为 O(N)。

6、迭代法(中序遍历)

代码

class Solution {
// 迭代法(中序遍历):使用栈,先将根节点入栈,然后不断弹出栈顶节点,交换其左右子树,并将右子树、左子树入栈,直到栈为空public:TreeNode* invertTree(TreeNode* root) {stack<TreeNode*> stk;if (root != nullptr) {stk.push(root);}while (!stk.empty()) {TreeNode* node = stk.top();if (node != nullptr) {stk.pop();// 将右子节点入栈if (node->right) {stk.push(node->right);}// 将当前节点再次入栈,用于后续交换左右子节点stk.push(node);stk.push(nullptr);// 将左子节点入栈if (node->left) {stk.push(node->left);}} else {stk.pop();// 取出需要交换的节点node = stk.top();stk.pop();// 交换左右子节点swap(node->left, node->right);}}return root;}
};

复杂度分析

  • 时间复杂度:O(N),其中 N 为二叉树节点的数目。我们会遍历二叉树中的每一个节点,对每个节点而言,我们在常数时间内交换其两棵子树。
  • 空间复杂度:O(N)。使用的空间由递归栈的深度决定,它等于当前节点在二叉树中的高度。在平均情况下,二叉树的高度与节点个数为对数关系,即 O(log⁡N)。而在最坏情况下,树形成链状,空间复杂度为 O(N)。

7、迭代法(后序遍历)

代码

class Solution {
// 迭代法(后序遍历):使用栈,先将根节点入栈,然后不断弹出栈顶节点,并将右子树、左子树入栈,交换其左右子树,直到栈为空
public:TreeNode* invertTree(TreeNode* root) {// 如果根节点为空,则直接返回空if (root == nullptr) return nullptr;// 创建一个栈,用于存储待处理的节点stack<TreeNode*> stk;// 将根节点入栈stk.push(root);// 当栈不为空时,循环处理栈中的节点while(!stk.empty()) {// 取出栈顶节点TreeNode* node = stk.top();// 将栈顶节点出栈stk.pop();// 如果当前节点的右子树不为空,则将右子树入栈if(node->right) stk.push(node->right);// 如果当前节点的左子树不为空,则将左子树入栈if(node->left) stk.push(node->left);// 交换当前节点的左右子树swap(node->left, node->right);}// 返回根节点return root;}
};

复杂度分析

  • 时间复杂度:O(N),其中 N 为二叉树节点的数目。我们会遍历二叉树中的每一个节点,对每个节点而言,我们在常数时间内交换其两棵子树。
  • 空间复杂度:O(N)。使用的空间由递归栈的深度决定,它等于当前节点在二叉树中的高度。在平均情况下,二叉树的高度与节点个数为对数关系,即 O(log⁡N)。而在最坏情况下,树形成链状,空间复杂度为 O(N)。

8、层序遍历(广度优先遍历)

思路

层序遍历也可以把每个节点的左右孩子都翻转一遍,我们可以使用队列,将根节点入队列,然后不断弹出队列头节点,交换其左右子树,并将右子树、左子树入队列,直到队列为空。

代码

class Solution {
// 层序遍历:使用队列,将根节点入队列,然后不断弹出队列头节点,交换其左右子树,并将右子树、左子树入队列,直到队列为空
public:TreeNode* invertTree(TreeNode* root) {// 创建一个队列用于存储待处理的节点queue<TreeNode*> que;// 如果根节点不为空,则将其加入队列if (root != nullptr) que.push(root);// 当队列不为空时,循环处理队列中的节点while (!que.empty()) {// 记录当前队列的大小int size = que.size();// 遍历当前队列中的所有节点for (int i = 0; i < size; i++) {// 取出队列中的节点TreeNode* node = que.front();// 将节点从队列中移除que.pop();// 交换节点的左右子树swap(node->left, node->right);// 如果节点的左子树不为空,则将其加入队列if (node->left) que.push(node->left);// 如果节点的右子树不为空,则将其加入队列if (node->right) que.push(node->right);}}// 返回处理后的根节点return root;}
};

复杂度分析

  • 时间复杂度:O(N),其中 N 为二叉树节点的数目。我们会遍历二叉树中的每一个节点,对每个节点而言,我们在常数时间内交换其两棵子树。
  • 空间复杂度:O(N)。使用的空间由递归栈的深度决定,它等于当前节点在二叉树中的高度。在平均情况下,二叉树的高度与节点个数为对数关系,即 O(log⁡N)。而在最坏情况下,树形成链状,空间复杂度为 O(N)。

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

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

相关文章

Sentinel流量防卫兵

1、分布式服务遇到的问题 服务可用性问题 服务可用性场景 服务雪崩效应 因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程&#xff0c;就叫服务雪崩效应导致服务不可用的原因&#xff1a; 在服务提供者不可用的时候&#xff0c;会出现大量重试的情况&…

Flink时间语义 | 大数据技术

⭐简单说两句⭐ ✨ 正在努力的小叮当~ &#x1f496; 超级爱分享&#xff0c;分享各种有趣干货&#xff01; &#x1f469;‍&#x1f4bb; 提供&#xff1a;模拟面试 | 简历诊断 | 独家简历模板 &#x1f308; 感谢关注&#xff0c;关注了你就是我的超级粉丝啦&#xff01; &a…

爬虫学习(2)破解百度翻译

代码 import requests import jsonif __name__ "__main__":url https://fanyi.baidu.com/sug#post请求参数处理&#xff08;同get请求一致&#xff09;headers {"User-Agent": Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, …

基于Springboot的果蔬作物疾病防治系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的果蔬作物疾病防治系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

ICode国际青少年编程竞赛- Python-1级训练场-识别循环规律1

ICode国际青少年编程竞赛- Python-1级训练场-识别循环规律1 1、 for i in range(4):Dev.step(6)Dev.turnLeft()2、 for i in range(3):Dev.turnLeft()Dev.step(2)Dev.turnRight()Dev.step(2)3、 for i in range(3):Spaceship.step(5)Spaceship.turnLeft()Spaceship.step(…

Linux字符设备驱动(一) - 框架

字符设备是Linux三大设备之一(另外两种是块设备&#xff0c;网络设备)&#xff0c;字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备&#xff0c;常见的字符设备包括鼠标、键盘、显示器、串口等等&#xff0c;当我们执行ls -l /dev的时候&#xff0c;就能看到大量…

2024年5月6日优雅草蜻蜓API大数据服务中心v2.0.3更新

v2.0.3更新 2024年5月6日优雅草蜻蜓API大数据服务中心v2.0.3更新-修复改版后搜索框漏掉的bug-增加搜索框 提示&#xff1a;优雅草大数据中心已经 上线137天 稳定运行 1181555 次 累积调用 目前大数据中心用户呈现增长趋势&#xff0c;目标2024年11月底突破1亿次调用&#xf…

021、Python+fastapi,第一个Python项目走向第21步:ubuntu 24.04 docker 安装mysql8集群、redis集群(二)

系列文章目录 pythonvue3fastapiai 学习_浪淘沙jkp的博客-CSDN博客https://blog.csdn.net/jiangkp/category_12623996.html 前言 安装redis 我会以三种方式安装&#xff0c;在5月4号修改完成 第一、直接最简单安装&#xff0c;适用于测试环境玩玩 第二、conf配置安装 第三…

Redis的数据类型及使用场景

redis命令大全官网: Commands | Docs (redis.io) 基本介绍 redis起初主要就是为了解决性能问题的&#xff0c;那么redis为什么快? 基于内存操作的&#xff0c;所以操作不需要跟磁盘进行交互&#xff0c;单次的执行会很快 命令执行是单线程 因为基于内存操作 单次执行时间反…

Java面试题:多线程3

CAS Compare and Swap(比较再交换) 体现了一种乐观锁的思想,在无锁情况下保证线程操作共享数据的原子性. 线程A和线程B对主内存中的变量c同时进行修改 在线程A中存在预期值a,修改后的更新值a1 在线程B中存在预期值b,修改后的更新值b1 当且仅当预期值和主内存中的变量值相等…

MYSQL基础架构、执行过程分析、事务的实现、索引的选择、覆盖索引

本文是mysql45讲的1-5的总结 文章目录 基础架构连接器分析器优化器执行器SQL查询执行过程详细执行步骤 SQL更新执行过程重要的日志模块&#xff1a;redo log重要的日志模块&#xff1a;binlog阶段性提交 事务事务隔离的实现启动 索引数据库索引模型InnoDB索引组织结构主键选择…

【数据可视化-02】Seaborn图形实战宝典

Seaborn介绍 Seaborn是一个基于Python的数据可视化库&#xff0c;它建立在matplotlib的基础之上&#xff0c;为统计数据的可视化提供了高级接口。Seaborn通过简洁美观的默认样式和绘图类型&#xff0c;使数据可视化变得更加简单和直观。它特别适用于那些想要创建具有吸引力且信…

从零开始学RSA: [WUSTCTF2020]情书等5题

1 [WUSTCTF2020]情书 题目 Premise: Enumerate the alphabet by 0、1、2、..... 、25 Using the RSA system Encryption:0156 0821 1616 0041 0140 2130 1616 0793 Public Key:2537 and 13 Private Key:2537 and 937flag: wctf2020{Decryption}解题 前提&#xff1a;用0、…

高效、精准:皮秒激光切割机在陶瓷基板加工中的应用

皮秒激光切割机&#xff08;激光划片机&#xff09;在陶瓷基板切割领域具有显著的优势和潜力&#xff0c;主要体现在以下几个方面&#xff1a; 1. 高精度&#xff1a;皮秒激光切割机能够实现极高的切割精度&#xff0c;对于陶瓷基板这种需要精细加工的材料尤为重要。它能够在不…

【网络原理】IP协议详解

一.与IP协议相关的基本概念 IP协议&#xff0c;即网际互连协议&#xff08;Internet Protocol&#xff09;&#xff0c;是TCP/IP体系中的核心网络层协议。 网络层IP协议解决的问题 数据传输的过程中,不是直接进行的传输,而是经过层层的封装和分用的过程才能到达对端. IP协议主…

13 【PS作图】人物绘画理论-脸型

三庭五眼 三庭&#xff1a;脸的长度比例 &#xff08;1&#xff09;发际线到眉毛 &#xff08;2&#xff09;眉毛到鼻底 &#xff08;3&#xff09;鼻底到下巴 三个部分大致为三等分 五眼&#xff1a;脸的宽度比例 以眼睛长度为单位&#xff0c;把脸的宽度分成五等分&#x…

day1Qt作业

#include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {this->resize(540,415);//窗口大小this->setFixedSize(540,415);//固定窗口大小this->setWindowTitle("QQ");//标题this->setWindowIcon(QIcon("E:\\hqyjap…

大数据在互联网领域的“九大”应用

当下越来越多的应用涉及到大数据&#xff0c;而这些大数据的属性&#xff0c;包括数量&#xff0c;速度&#xff0c;多样性等等都呈现出大数据不断增长的复杂性&#xff0c;所以大数据的分析方法在大数据领域就显得尤为重要&#xff0c;目前互联网大数据运用的九大领域&#xf…

网络演进技术演进:裸纤专线、SDH、MSTP+、OTN、PTN、IP-RAN

前言 文章主要介绍常见名词以及其在各自领域实现的功能价值。 01 裸纤 裸光纤&#xff08;裸光纤&#xff09;由运营商提供&#xff0c;是无中继的光纤线路&#xff0c;仅通过配线架连接。相比传统光纤&#xff0c;裸光纤提供纯粹的物理传输路径&#xff0c;无需额外网…

Linux字符设备驱动-详解与实操:驱动架构、设备树、Pinctrl子系统和GPIO子系统、platform、设备树下的platform

如何编写一个驱动程序&#xff1a; &#xff08;1&#xff09;确定主设备号 &#xff08;2&#xff09;定义自己的file_operations结构体&#xff1a; 包含对应的open(drv_open)/read(drv_read)等设备操作函数&#xff0c;需要到内核中去注册 &#xff08;3&#xff09;实现…