创作

完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>

3天内不再提示

如何才能够翻转二叉树

T3ru_xincailiao 来源:代码随想录 作者:程序员Carl 2021-09-01 11:45 次阅读

这道题目是非常经典的题目,也是比较简单的题目(至少一看就会)。

但正是因为这道题太简单,一看就会,一些同学都没有抓住起本质,稀里糊涂的就把这道题目过了。

如果做过这道题的同学也建议认真看完,相信一定有所收获!

226.翻转二叉树题目地址:https://leetcode-cn.com/problems/invert-binary-tree/

翻转一棵二叉树。

这道题目背后有一个让程序员心酸的故事,听说 Homebrew的作者Max Howell,就是因为没在白板上写出翻转二叉树,最后被Google拒绝了。(真假不做判断,权当一个乐子哈)

思路我们之前介绍的都是各种方式遍历二叉树,这次要翻转了,感觉还是有点懵逼。

这得怎么翻转呢?

如果要从整个树来看,翻转还真的挺复杂,整个树以中间分割线进行翻转,如图:

可以发现想要翻转它,其实就把每一个节点的左右孩子交换一下就可以了。

关键在于遍历顺序,前中后序应该选哪一种遍历顺序?(一些同学这道题都过了,但是不知道自己用的是什么顺序)

遍历的过程中去翻转每一个节点的左右孩子就可以达到整体翻转的效果。

注意只要把每一个节点的左右孩子翻转一下,就可以达到整体翻转的效果

这道题目使用前序遍历和后序遍历都可以,唯独中序遍历不行,因为中序遍历会把某些节点的左右孩子翻转了两次!建议拿纸画一画,就理解了

那么层序遍历可以不可以呢?依然可以的!只要把每一个节点的左右孩子翻转一下的遍历方式都是可以的!

递归法对于二叉树的递归法的前中后序遍历,已经在二叉树:前中后序递归遍历详细讲解了。

我们下文以前序遍历为例,通过动画来看一下翻转的过程:

我们来看一下递归三部曲:

确定递归函数的参数和返回值

参数就是要传入节点的指针,不需要其他参数了,通常此时定下来主要参数,如果在写递归的逻辑中发现还需要其他参数的时候,随时补充。

返回值的话其实也不需要,但是题目中给出的要返回root节点的指针,可以直接使用题目定义好的函数,所以就函数的返回类型为TreeNode*。

TreeNode* invertTree(TreeNode* root)

确定终止条件

当前节点为空的时候,就返回

if (root == NULL) return root;

确定单层递归的逻辑

因为是先前序遍历,所以先进行交换左右孩子节点,然后反转左子树,反转右子树。

swap(root-》left, root-》right);

invertTree(root-》left);

invertTree(root-》right);

基于这递归三步法,代码基本写完,C++代码如下:

class Solution {public:

TreeNode* invertTree(TreeNode* root) {

if (root == NULL) return root;

swap(root-》left, root-》right); // 中

invertTree(root-》left); // 左

invertTree(root-》right); // 右

return root;

}

};

迭代法深度优先遍历二叉树:听说递归能做的,栈也能做!中给出了前中后序迭代方式的写法,所以本地可以很轻松的切出如下迭代法的代码:

C++代码迭代法(前序遍历)

class Solution {public:

TreeNode* invertTree(TreeNode* root) {

if (root == NULL) return root;

stack《TreeNode*》 st;

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;

}

};

如果这个代码看不懂的话可以在回顾一下二叉树:听说递归能做的,栈也能做!。

我们在二叉树:前中后序迭代方式的统一写法中介绍了统一的写法,所以,本题也只需将文中的代码少做修改便可。

C++代码如下迭代法(前序遍历)

class Solution {public:

TreeNode* invertTree(TreeNode* root) {

stack《TreeNode*》 st;

if (root != NULL) 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;

}

};

如果上面这个代码看不懂,回顾一下文章二叉树:前中后序迭代方式的统一写法。

广度优先遍历也就是层序遍历,层数遍历也是可以翻转这棵树的,因为层序遍历也可以把每个节点的左右孩子都翻转一遍,代码如下:

class Solution {public:

TreeNode* invertTree(TreeNode* root) {

queue《TreeNode*》 que;

if (root != NULL) 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;

}

};

如果对以上代码不理解,或者不清楚二叉树的层序遍历,可以看这篇二叉树:层序遍历登场!

总结针对二叉树的问题,解题之前一定要想清楚究竟是前中后序遍历,还是层序遍历。

二叉树解题的大忌就是自己稀里糊涂的过了(因为这道题相对简单),但是也不知道自己是怎么遍历的。

这也是造成了二叉树的题目“一看就会,一写就废”的原因。

针对翻转二叉树,我给出了一种递归,三种迭代(两种模拟深度优先遍历,一种层序遍历)的写法,都是之前我们讲过的写法,融汇贯通一下而已。

大家一定也有自己的解法,但一定要成方法论,这样才能通用,才能举一反三!

其他语言版本Java://DFS递归class Solution {

/**

* 前后序遍历都可以

* 中序不行,因为先左孩子交换孩子,再根交换孩子(做完后,右孩子已经变成了原来的左孩子),再右孩子交换孩子(此时其实是对原来的左孩子做交换)

*/

public TreeNode invertTree(TreeNode root) {

if (root == null) {

return null;

}

invertTree(root.left);

invertTree(root.right);

swapChildren(root);

return root;

}

private void swapChildren(TreeNode root) {

TreeNode tmp = root.left;

root.left = root.right;

root.right = tmp;

}

}

//BFSclass Solution {

public TreeNode invertTree(TreeNode root) {

if (root == null) {return null;}

ArrayDeque《TreeNode》 deque = new ArrayDeque《》();

deque.offer(root);

while (!deque.isEmpty()) {

int size = deque.size();

while (size-- 》 0) {

TreeNode node = deque.poll();

swap(node);

if (node.left != null) {deque.offer(node.left);}

if (node.right != null) {deque.offer(node.right);}

}

}

return root;

}

public void swap(TreeNode root) {

TreeNode temp = root.left;

root.left = root.right;

root.right = temp;

}

}

Python递归法:前序遍历:

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 root

st = []

st.append(root)

while st:

node = st.pop()

node.left, node.right = node.right, node.left #中

if node.right:

st.append(node.right) #右

if node.left:

st.append(node.left) #左

return root

迭代法:广度优先遍历(层序遍历):

import collections

class Solution:

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

queue = collections.deque() #使用deque()

if root:

queue.append(root)

while queue:

size = len(queue)

for i in range(size):

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

责任编辑:haq

  • C++
    C++
    +关注

    关注

    18

    文章

    1466

    浏览量

    67696
  • 代码
    +关注

    关注

    20

    文章

    2279

    浏览量

    60385
  • 二叉树
    +关注

    关注

    0

    文章

    43

    浏览量

    11074
收藏 人收藏

    评论

    相关推荐

    安全关键软件的非侵入式代码覆盖

      高效的目标虚拟化,再加上一个从执行跟踪数据中推断出精确的源级覆盖率指标的工具,用于非仪器化/未修....
    的头像 星星科技指导员 发表于 06-28 15:50 69次 阅读
    安全关键软件的非侵入式代码覆盖

    汽车系统开发中的软件质量计划

      汽车行业正处于软件应用程序快速增长和成熟的时期。人们认识到需要将功能增强与质量计划相匹配,并将这....
    的头像 星星科技指导员 发表于 06-28 15:01 62次 阅读

    INSOperationsKit Advanced NSOperations会议代码样本

    ./oschina_soft/INSOperationsKit.zip
    发表于 06-28 14:32 3次 阅读
    INSOperationsKit Advanced NSOperations会议代码样本

    模型驱动测试如何生成基于代码的测试结果

      寻找方法帮助分布式团队更好地协同工作,同时推动高质量的可交付成果是许多组织的首要任务。当开发过程....
    的头像 星星科技指导员 发表于 06-28 14:12 90次 阅读
    模型驱动测试如何生成基于代码的测试结果

    静态分析有助于代码可移植性

      在项目生命周期中尽早采用静态分析将确保尽早验证遗留代码,并确保任何新代码从一开始就可移植。通过缩....
    的头像 星星科技指导员 发表于 06-28 11:56 88次 阅读
    静态分析有助于代码可移植性

    LXFPhotoHelper调用系统相机与相册

    ./oschina_soft/LXFPhotoHelper.zip
    发表于 06-28 11:49 1次 阅读
    LXFPhotoHelper调用系统相机与相册

    开源软件-CodeFever Git代码托管服务

    ./oschina_soft/codefever.zip
    发表于 06-28 11:35 1次 阅读
    开源软件-CodeFever Git代码托管服务

    「Spring」认证安全架构指南

    本指南是 Spring Security 的入门指南,提供对框架设计和基本构建块的深入了解。我们仅涵....
    的头像 「Spring」认证安全架构 发表于 06-27 14:37 18次 阅读

    OAuthSwiftFutures为OAuthSwift增加了futures/promises

    ./oschina_soft/OAuthSwiftFutures.zip
    发表于 06-27 11:33 3次 阅读
    OAuthSwiftFutures为OAuthSwift增加了futures/promises

    CYLTableViewPlaceHolder占位视图管理

    ./oschina_soft/CYLTableViewPlaceHolder.zip
    发表于 06-27 11:27 1次 阅读
    CYLTableViewPlaceHolder占位视图管理

    A-VibrancyView iOS模糊和镂空透明层

    ./oschina_soft/A-VibrancyView.zip
    发表于 06-27 09:57 3次 阅读
    A-VibrancyView iOS模糊和镂空透明层

    XZMCoreNewFeature版本新特性框架

    ./oschina_soft/XZMCoreNewFeature.zip
    发表于 06-27 09:42 3次 阅读
    XZMCoreNewFeature版本新特性框架

    怎么开发启动框架plugin

    在移动端中启动 Flutter 页面会有短暂空白,虽然官方提供了引擎预热机制,但是需要提前将所有页面....
    的头像 谷歌开发者 发表于 06-24 16:28 304次 阅读

    FFToast iOS消息提醒控件

    ./oschina_soft/FFToast.zip
    发表于 06-24 11:06 3次 阅读
    FFToast iOS消息提醒控件

    LibSourcey C++高性能网络开发库

    ./oschina_soft/libsourcey.zip
    发表于 06-24 11:00 8次 阅读
    LibSourcey C++高性能网络开发库

    GXWaterCollectionViewLayout可设置纵横方向和排列数的瀑布流布局

    ./oschina_soft/GXWaterCollectionViewLayout.zip
    发表于 06-24 10:56 3次 阅读
    GXWaterCollectionViewLayout可设置纵横方向和排列数的瀑布流布局

    警惕C++中的异常处理

      许多编译器默认包含 EHS 代码。这意味着不知情的用户会自动合并开销,即使他们无意使用 EHS。....
    发表于 06-24 10:31 348次 阅读
    警惕C++中的异常处理

    Valet钥匙链中存储数据的iOS库

    ./oschina_soft/Valet.zip
    发表于 06-24 10:21 12次 阅读
    Valet钥匙链中存储数据的iOS库

    FXDanmaku高性能弹幕库

    ./oschina_soft/FXDanmaku.zip
    发表于 06-24 10:17 9次 阅读
    FXDanmaku高性能弹幕库

    HDAlertView类似iOS alertView弹窗组件

    ./oschina_soft/HDAlertView.zip
    发表于 06-24 10:15 3次 阅读
    HDAlertView类似iOS alertView弹窗组件

    TeamTalk4Mac中小型企业内部通讯IM

    ./oschina_soft/teamtalk.zip
    发表于 06-24 09:49 3次 阅读
    TeamTalk4Mac中小型企业内部通讯IM

    开源软件-Zapcc基于Clang的C++编译器

    ./oschina_soft/zapcc.zip
    发表于 06-23 15:17 8次 阅读
    开源软件-Zapcc基于Clang的C++编译器

    开源软件-uftrace C/C++ 程序的跟踪和分析工具

    ./oschina_soft/uftrace.zip
    发表于 06-23 15:06 9次 阅读
    开源软件-uftrace C/C++ 程序的跟踪和分析工具

    哈希是什么,常见的哈希算法有哪些

    什么是哈希? 哈希又称作“散列”,是一种数学计算机程序,它接收任何一组任意长度的输入信息,通过哈希算....
    的头像 18125913365 发表于 06-23 14:57 98次 阅读

    ThreadStacks C/C++进程堆栈追踪库

    ./oschina_soft/threadstacks.zip
    发表于 06-23 14:49 8次 阅读
    ThreadStacks C/C++进程堆栈追踪库

    CLWheelMenuView Swift转盘菜单

    ./oschina_soft/CLDemo.zip
    发表于 06-23 11:00 9次 阅读
    CLWheelMenuView Swift转盘菜单

    cpgf C++跨平台多功能扩展库

    ./oschina_soft/cpgf.zip
    发表于 06-23 10:39 7次 阅读
    cpgf C++跨平台多功能扩展库

    eventpp C++事件派发和回调代码库

    ./oschina_soft/eventpp.zip
    发表于 06-23 10:38 4次 阅读
    eventpp C++事件派发和回调代码库

    Gincu C++ 2D游戏引擎

    ./oschina_soft/gincu.zip
    发表于 06-23 10:37 6次 阅读
    Gincu C++ 2D游戏引擎

    PcapPlusPlus网络嗅探和包装分析制作框架

    ./oschina_soft/PcapPlusPlus.zip
    发表于 06-23 10:26 6次 阅读
    PcapPlusPlus网络嗅探和包装分析制作框架

    Fizz C++ 14实现的TLS 1.3标准库

    ./oschina_soft/fizz.zip
    发表于 06-23 10:25 6次 阅读
    Fizz C++ 14实现的TLS 1.3标准库

    mongols C++服务器基础设施

    ./oschina_soft/mongols.zip
    发表于 06-23 10:15 4次 阅读
    mongols C++服务器基础设施

    libaco轻量级C非对称协程库

    ./oschina_soft/libaco.zip
    发表于 06-23 10:11 6次 阅读
    libaco轻量级C非对称协程库

    将RISC-V融入到工业产品线开发流程中

      关键信息是嵌入式软件工程师将在定义 SoC 架构,特别是编程模型和系统优化方面发挥更大的作用。开....
    的头像 星星科技指导员 发表于 06-22 16:06 201次 阅读
    将RISC-V融入到工业产品线开发流程中

    Dragonboat Go实现的多组Raft库

    ./oschina_soft/dragonboat.zip
    发表于 06-22 15:03 5次 阅读
    Dragonboat Go实现的多组Raft库

    安富莱C语言编码规范

    以下提供两种命名方式以供参考:(1)各程序模块的文件命名开头 2 个小写字母代表本模块的功能:如:主....
    的头像 硬件攻城狮 发表于 06-22 14:38 129次 阅读

    利用汽车开发标准如何降低风险

      底线是汽车应用的端到端测试过于昂贵和复杂。另一方面,软件故障的成本应该成为寻找降低风险方法的动力....
    的头像 星星科技指导员 发表于 06-22 14:37 87次 阅读

    ColorfulConsoleIO终端输出彩色字符库

    ./oschina_soft/gitee-ColorfulConsoleIO.zip
    发表于 06-22 14:21 6次 阅读
    ColorfulConsoleIO终端输出彩色字符库

    NumCpp C++版本的Numpy

    ./oschina_soft/NumCpp.zip
    发表于 06-22 14:16 16次 阅读
    NumCpp C++版本的Numpy

    CDT 4.0提高生产力并提供更大的可扩展性

      对 Windows SDK 的支持:最近,Microsoft 提供了它的编译器作为其 Windo....
    的头像 星星科技指导员 发表于 06-22 11:30 93次 阅读
    CDT 4.0提高生产力并提供更大的可扩展性

    CIDLib C++开发平台

    ./oschina_soft/CIDLib.zip
    发表于 06-22 11:26 11次 阅读
    CIDLib C++开发平台

    ejson轻量简单的C++ JSON解析库

    ./oschina_soft/ejson.zip
    发表于 06-22 11:22 6次 阅读
    ejson轻量简单的C++ JSON解析库

    你应该知道的18个PyTorch小技巧

    我首先提供一个完整的列表和一些代码片段,这样你就可以开始优化你的脚本了。然后我一个一个地详细地研究它....
    的头像 OpenCV学堂 发表于 06-22 10:00 220次 阅读

    ImGUI C++即时渲染UI组件

    ./oschina_soft/imgui.zip
    发表于 06-22 09:59 14次 阅读
    ImGUI C++即时渲染UI组件

    tinyserver C++编写的轻量服务器框架

    ./oschina_soft/tinyserver.zip
    发表于 06-22 09:53 8次 阅读
    tinyserver C++编写的轻量服务器框架

    gobject_cpp11基于C++11实现的信号槽

    ./oschina_soft/gitee-gob<x>ject_cpp11.zip
    发表于 06-22 09:48 11次 阅读
    gobject_cpp11基于C++11实现的信号槽

    gobject_cpp98基于ANSI C++实现的信号槽

    ./oschina_soft/gitee-gob<x>ject_cpp98.zip
    发表于 06-22 09:47 8次 阅读
    gobject_cpp98基于ANSI C++实现的信号槽

    clipp C++命令行界面

    ./oschina_soft/clipp.zip
    发表于 06-22 09:19 15次 阅读
    clipp C++命令行界面

    求助,打开DevEco Studio看代码的时候注释中文全变成乱码的原因是什么?

    不知道为什么,今天打开DevEcoStudio,看代码的时候,注释中文全变成乱码了,求助!! ...
    发表于 06-10 10:29 380次 阅读

    【飞控开发高级篇2】疯壳·开源编队无人机-遥控整机代码走读、编译与烧写

    COCOFLY教程——疯壳无人机·系列遥控整机代码走读、编译与烧写 图1 一、代码架构  遥控的整体代码工程...
    发表于 06-08 16:00 942次 阅读
    【飞控开发高级篇2】疯壳·开源编队无人机-遥控整机代码走读、编译与烧写

    【飞控开发高级篇】疯壳·开源编队无人机-飞控整机代码走读、编译与烧写

    COCOFLY教程——疯壳·无人机系列飞控整机代码走读、编译与烧写 图1 一、代码架构  飞控的整体代码工程由...
    发表于 06-07 18:16 4345次 阅读
    【飞控开发高级篇】疯壳·开源编队无人机-飞控整机代码走读、编译与烧写

    CH569的HSPI代码测试的速度很慢如何处理?

    看手册写的最高速度达到3.8Gbps,有测试Demo吗。 用HSPI_BurstMode代码测试的感觉速度也就300MByte/s+,不知道是哪出...
    发表于 06-01 06:10 91次 阅读

    求助大神,rt_ringbuffer_peak疑问求解

    rt_size_t rt_ringbuffer_peak(struct rt_ringbuffer *rb, rt_uint8_t **ptr) {     RT_ASSERT(rb != RT_...
    发表于 05-27 11:30 2094次 阅读

    请问CH32V103的引导代码是可以修改的吗?

    这是否意味着我可以把出货的产品引导代码的烧录和调试功能给彻底去掉,从而避免芯片被利用引导程序BUG破解.提高安全性. &...
    发表于 05-18 06:23 181次 阅读

    【开发教程9】人形街舞机器人-整机代码

    整机代码            1相关简介        本章将结合前面实验章节,完成机器人...
    发表于 05-17 16:40 4218次 阅读
    【开发教程9】人形街舞机器人-整机代码

    小白福利!教你用低代码实现一个简单的页面跳转功能

    一、介绍 HUAWEI DevEco Studio(后文简称:IDE)自2020年9月首次发布以来,经10次迭代升级,不断为HarmonyOS...
    发表于 05-16 17:22 5990次 阅读

    OpenHarmony仓库大整理 可以指定系统类型下载对应代码

    前言: 以前下载OpenHarmony代码的时候,我们都是需要下载全量包,代码量非常大,现在已经有30多G了。 而我们如果只是想开发...
    发表于 05-12 15:44 538次 阅读

    【开发教程11】开源蓝牙心率防水运动手环- 整机功能代码讲解

    整机功能代码讲解 1 软件设计   本节,我们将融合前面的蓝牙收发、三轴记步、电量检测、外部 Flash 读写、 心率...
    发表于 05-12 11:59 3545次 阅读