0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

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

3天内不再提示

如何才能够翻转二叉树

新材料在线 来源:代码随想录 作者:程序员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++
    +关注

    关注

    22

    文章

    2131

    浏览量

    77487
  • 代码
    +关注

    关注

    30

    文章

    4983

    浏览量

    74533
  • 二叉树
    +关注

    关注

    0

    文章

    74

    浏览量

    13024

原文标题:你真的会翻转二叉树么?

文章出处:【微信号:xincailiaozaixian,微信公众号:新材料在线】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    UniStore正式全面开放

    5月7日,宇科技正式宣布,全球首个人形机器人任务动作应用商店——宇UniStore官方共享应用平台即日起面向全球用户全面开放。用户可通过该平台开发和下载机器人应用,像安装手机App一样简单,无需任何底层编程能力。
    的头像 发表于 05-09 11:22 1084次阅读

    科技,IPO申请获受理

    电子发烧友网综合报道 3月20日,上交所网站显示,宇科技股份有限公司科创板IPO申请已受理,成为又一家科创板IPO“预先审阅”落地项目。此次IPO,宇科技拟募资42.02亿元。   招股书显示
    的头像 发表于 03-20 18:33 4400次阅读
    宇<b class='flag-5'>树</b>科技,IPO申请获受理

    嵌入式C语言高质量编程:从“能用”到“卓越”的跨越

    只有掌握了嵌入式C硬核的技术,才能够铸就工业级高质量的代码。
    的头像 发表于 03-13 10:18 303次阅读
    嵌入式C语言高质量编程:从“能用”到“卓越”的跨越

    入门宇机器人开发:从SDK源码探索到实战操作

    机器人(Unitree)作为全球领先的四足机器人研发企业,其推出的unitree_sdk2是面向旗下 Go2、H1、B2 等系列机器人的第代软件开发工具包。该 SDK 提供了丰富的接口和示例代码,支持开发者快速实现机器人控制、状态获取、传感器数据处理等功能,是入门宇
    的头像 发表于 02-06 16:43 3642次阅读
    入门宇<b class='flag-5'>树</b>机器人开发:从SDK源码探索到实战操作

    TÜV莱茵与杭集团达成战略合作并颁发欧盟CE-MD符合性证书

    日前,国际独立第三方检测、检验和认证机构德国莱茵TÜV大中华区(简称"TÜV莱茵")与杭集团股份有限公司(简称"杭集团")签署了战略合作协议,标志着双方
    的头像 发表于 01-15 12:18 520次阅读

    亿纬锂能与杭集团达成战略合作

    近日,亿纬锂能与杭集团2025年战略研讨会暨战略合作协议签约仪式在杭州举行。亿纬锂能副总裁、商用车电池产品线总裁江吉兵博士,亿纬锂能商用车电池产品线国内销售部总经理井振江,杭集团董事、副总经理兼
    的头像 发表于 01-04 18:18 1230次阅读

    【OK3506-S12Mini试用评测()】开发板SDK配置动态设备

    在配好的虚拟机的终端输入./build.sh bconfig,选择Kernal 进去之后选择图中选项(按Y确定) Defconfig name 需要在终端输入命令,才能得到需要写的名字。 动态设备的名字是在虚拟机中找到要用的的dts文件。
    发表于 11-19 17:09

    通过优化代码来提高MCU运行效率

    选择时间复杂度低的算法。 根据访问模式选择数据结构。频繁查找用哈希表,有序数据用二叉树等。 查表法:对于复杂的数学计算(如sin, log),或者协议解析,预先计算好结果存于数组中,用空间换时间
    发表于 11-12 08:21

    蜂鸟E203内核中断管理模块sirv_plic_man代码分析

    。 上面的代码生成一个二叉树结构来比较和选择具有最大优先级的挂起中断源及其ID。树状结构由级联比较器组成,每一层的比较器数量是前一层的一半。在的每一层,选择优先级最高的中断并传递到下一层,直到只剩下
    发表于 10-23 06:05

    请问rtt studio 的文件夹打红什么意思?

    rtt studio 的文件夹打红什么意思?而且文件夹里面实际是有文件的,但是浏览不出来。
    发表于 09-18 06:34

    机器人看点:宇新专利可提升机器人表演效果 蔚来资本入股具身智能公司原力灵机 美信科技新设机器人制

    。宇科技的新专利通过构建环境采集模块、地图处理模块、数字舞台孪生模块、舞蹈动作设计模块、轨迹规划模块、舞蹈合成模块,进行数据交互和功能协同,能够确保机器人能够准确感知和适应舞台环境的变化,使得机器人动作
    的头像 发表于 09-01 16:55 2201次阅读

    科技,被起诉

    电子发烧友网综合报道 天眼查显示,近日,杭州宇科技股份有限公司(以下简称“宇科技”)新增1条开庭公告,原告为杭州露韦美日化有限公司(以下简称“露韦美日化”),案由为侵害发明专利权纠纷,该案将于8
    的头像 发表于 08-26 07:50 5317次阅读
    宇<b class='flag-5'>树</b>科技,被起诉

    在使用EZ-USB® FX3™ 设备时,上电后相机开始正常工作,但延时10s左右播放器才能够显示图像数据?为什么?

    在使用EZ-USB® FX3™ 设备时,上电后相机开始正常工作,但延时10s左右播放器才能够显示图像数据?这是由于固件中的某些设置问题吗?
    发表于 07-16 07:08

    亿纬锂能荣获杭集团2022-2024年度优秀供应商奖

    近日,亿纬锂能凭借卓越产品、可靠交付与优质服务荣获杭集团颁发的“2022-2024年度优秀供应商”奖。杭集团副总经理兼杭电器董事长金华曙、杭电器总经理兼杭博电机总经理李明辉出席
    的头像 发表于 07-15 09:00 1158次阅读

    下一代高速芯片晶体管解制造问题解决了!

    晶体管的密度,同时减少了芯片的横向面积。 相比传统的FinFET和纳米片晶体管,片晶体管能够显著减少nFET和pFET之间的间距,从而在相同的芯片面积上容纳更多的晶体管。例如,IMEC的2nm片晶
    发表于 06-20 10:40