【数据结构】--二叉树递归题记

最近写了几道关于二叉树的剑指offer题,和小伙伴们分享一下心得。

🌈对称的二叉树

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。

 思路分析:

对于二叉树的问题来说肯定是用递归进行解决。至于如何解决有待考究,但是

第一步肯定是判断root是不是空。

第二步是进行递归到左右子树进行比较子树的值。这里会遇到两种情况:

  1. 若是都为空那就是对称的返回true.
  2. 若只有一个节点为空或者对称节点间的val值不等,则返回false,因为这两种情况下,该二叉树不满足对称的要求。

第三步:如果对称节点的值相等,则需要进一步比较左子树的左孩子与右子树的右孩子是否对称,以及左子树的右孩子与右子树的左孩子是否对称,若都对称则返回true,否则返回false。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        // 如果是空树
        if(!root)
        //如果结点不是空就进入判断,但是这个逻辑取反,如果是空就进入判断
            return true;
        else
        //进入子节点继续比较
            return isSymmetric(root->left, root->right);
    }
    // 函数重载,此函数比较二叉树中位置对称的两个节点
    bool isSymmetric(TreeNode* left, TreeNode* right){
        // 结束条件1:如果对称两个节点都为空,则返回true
        if(!left && !right){
            return true;
        }
        // 结束条件2:如果单独一个节点为空,另一个节点不为空,又或者是对称节点间的val值不等,则返回false
        if(!left || !right || left->val != right->val)
            return false;
        // 结点不是空并且相等
        return isSymmetric(left->left, right->right) && isSymmetric(left->right, right->left);      
    }
};

🌈二叉树的镜像 

请完成一个函数,输入一个二叉树,该函数输出它的镜像。

  • 例如输入:

                    4
                   /   \
                 2      7
                / \      / \
              1   3  6   9

  • 镜像输出:

                     4
                    /   \
                 7      2
                 / \      / \
               9   6  3   1

 解题思路:

  • 第一步:根节点是空
  • 第二步:一直递归直到进到最底层根节点位置。从底层开始交换。
  • 第三步:分别记录下最左边,最右边子树的结点值,然后交换,这样层层交换,最后实现镜像。
class Solution {
public:
    TreeNode* mirrorTree(TreeNode* root) {
        if (root == nullptr) {
            return nullptr;
        }
        TreeNode* left = mirrorTree(root->left);
        TreeNode* right = mirrorTree(root->right);
        root->left = right;
        root->right = left;
        return root;
    }
};

先在栈中存入4,先递归的是左子树,所以把2存入栈中,继续递归到左子树1,但是1是空节点,返回到根2,然后递归2的右子树3,存入栈中,交换1,3后出栈。返回根节点2。

栈底栈底
44
22
1...
3
...

然后递归2的根节点4的右子树,把7压入栈中。同理压入左右子树6,9

栈底栈底
44
22
...7
6
9 ...
交换左右子树后出栈并且返回根节点7。    再交换2,7并且出栈。最后把根节点4出栈    .返回根节点4.         
栈底栈底
44
2...
7...
                                                                       

🌈二叉树剪枝 

给定一个二叉树 根节点 root ,树的每个节点的值要么是 0,要么是 1。请剪除该二叉树中所有节点的值为 0 的子树。

节点 node 的子树为 node 本身,以及所有 node 的后代。

剪枝后的二叉树满足如下要求:

  • 对于每个节点,如果该节点为叶子节点(没有左右子树),且该节点的值为0,则将该节点剪掉。
  • 对于非叶子节点,如果其左子树和右子树都被剪掉了(即为空指针),且该节点的值为0,则将该节点剪掉。

具体实现思路:递归地对每个节点进行处理,首先对其左右子树进行递归,然后判断当前节点是否为叶子节点,如果是则判断其值是否为0,如果是则将该节点剪掉,返回nullptr;如果不是叶子节点,则判断其左右子树是否都为空指针且该节点的值是否为0,如果是则将该节点剪掉,返回nullptr;否则直接返回该节点的指针。

这个最重要的问题就是如何实现把该剪枝的部分置为空?

如果需要被剪枝,则返回nullptr,将当前节点的左子树指针置为nullptr。

class Solution {
public:
    TreeNode* pruneTree(TreeNode* root) {
        if (root == nullptr) {
            return nullptr;
        }
        
        root->left = pruneTree(root->left);
         //这一句代码的作用是递归调用pruneTree函数来判断当前节点的
        //左子树是否需要被剪枝,如果需要被剪枝,则返回nullptr,将当前节点的左子树指针置为nullptr,
        root->right = pruneTree(root->right);
        
        if (root->left == nullptr && root->right == nullptr && root->val == 0) {
            return nullptr;
        }
        
        return root;
    }
};

你们发现没。这种二叉树的递归问题一般都是从下往上或者从上往下整活。但是从下往上用的比较多虽然效率不高。我们拿第二个举例:

             1

         /       \

      0           1

   /     \       /    \

0      0     0      1

先把1存入栈中,然后递归左子树把0存入栈,在存入0的左子树,

栈底返回值
11
0nullptr
0nullptr

0给根返回空并且出栈,然后调用0的右子树,入栈,它的左右子树都是0,返回nullptr.

同第一左根节点0的左右子树都是0,也进行赋值为nullptr并且出栈。然后1的右子树进栈执行同样操作。

栈底栈底
11
11
01
同理0出栈,1进栈。再返回到第一右子节点1.然后1的左子树赋值为nullptr,最后返回到根节点1.剪枝完成。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

谷达冠楠:抖音开网店创业怎么做

随着互联网的发展,越来越多的人选择在网上创业。而抖音作为目前最火的短视频平台之一,也成为了许多人开网店的首选。那么,如何在抖音上开网店创业呢?下面就来详细介绍一下。 第一步:注册账号 首先,你需要在抖音上注册…

登录模块的实现

一.前期的准备工作 1.页面的布局 (1)表单的校验: 利用element-ui提供的文档绑定rules规则后实现校验 (2)跨域的配置 : 利用proxy代理来解决跨域的问题 (3)axios拦截器的配置 两个点:1. 在请求拦截的成功回调中,如果token,因为调用其它的接口需要token才能调取。 在请…

【排序】对各种排序的总结

文章目录 前言1. 排序算法的复杂度及稳定性分析2. 排序算法的性能测试2.1 重复率较低的随机值排序测试2.2 重复率较高的随机值排序测试 前言 本篇是基于我这几篇博客做的一个总结: 《简单排序》(含:冒泡排序,直接插入排序&#x…

【Docker】概述与安装

🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于Docker的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 一. Docker的概述 1.Docker为什么出现 2…

【AI视野·今日CV 计算机视觉论文速览 第285期】Mon, 8 Jan 2024

AI视野今日CS.CV 计算机视觉论文速览 Mon, 8 Jan 2024 Totally 66 papers 👉上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Denoising Vision Transformers Authors Jiawei Yang, Katie Z Luo, Jiefeng Li, Kilian Q Weinberger, Yonglong Tian, Yue…

YOLOv8-Seg改进:轻量化改进 | 超越RepVGG!浙大阿里提出OREPA:在线卷积重参数化

🚀🚀🚀本文改进:OREPA在线卷积重参数化巧妙的和YOLOV8结合,并实现轻量化 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-seg; 2)模型创新,提升分割性能; 3)独家…

(css样式)权限控制el-button是否显示 + 鼠标悬浮停留才会显示el-button

前提: (1)当前物理席位是主任席(seatType‘1’) (2)管制席位TWR_ONE账号发布了内容:管制席——zhouzebiao——。。。。 (3)主任席tatai账号发布了内容&…

C++|47.动态数组 48.C++的std:vector使用优化

动态数组 动态数组叫vector,也是一种定义好的类/数据结构。“定义好”意味着 vector处在std命名空间之中。 vector的存在代表着一种可以调用的数据结构,不用 动态的意思是可以将该数组的大小进行动态调整。 也就意味着起初vector是没有固定大小的。 它是…

Git 基础指令

Git 基础指令 本章涵盖了我们在使用 Git 完成各种操作时将会用到的各种基本命令。 在学习完本章之后,我们应该能够配置并初始化一个仓库(repository)、开始或停止跟踪(track)文件、暂存(stage)…

QT第四天

头文件&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include<QTime>//时间类 #include<QTimerEvent>//定时器事件类 #include<QtTextToSpeech> //语言播报类 #include<QPushButton> namespace Ui { class Widget; }clas…

【Scala】——变量数据类型运算符

1. 概述 1.1 Scala 和 Java 关系 1.2 scala特点 Scala是一门以Java虚拟机&#xff08;JVM&#xff09;为运行环境并将面向对象和函数式编程的最佳特性结合在一起的静态类型编程语言&#xff08;静态语言需要提前编译的如&#xff1a;Java、c、c等&#xff0c;动态语言如&#…

js 数据回调 异步 Promise

回调顺序 JavaScript 函数按照它们被调用的顺序执行。而不是以它们被定义的顺序。 js数据顺序问题 <!DOCTYPE html> <html> <body><h2>JavaScript 函数序列</h2><p>JavaScript 函数按照它们被调用的顺序执行。</p><p id"de…

[足式机器人]Part2 Dr. CAN学习笔记-Advanced控制理论 Ch04-3Phase Portrait相图,相轨迹

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-Advanced控制理论 Ch04-3Phase Portrait相图&#xff0c;相轨迹 1. 1-D2. 2-D3. General Form4. Summary5. 爱情中的数学-Phase Portrait 相图动态系统分析 1. 1-D 2. 2-D 3. General Form 4. Su…

你为什么还在用Promise.all?

请停止在JavaScript中使用Promise.all() 什么是JavaScript中的Promise 如果您偶然发现这篇文章,那么您可能已经熟悉了promise。 但是,对于那些JavaScript新手来说,让我们来详细说明一下。 从本质上讲,Promise对象表示异步操作的最终完成或失败。 有趣的是,当创建promise时,其值…

【昕宝爸爸小模块】ConcurrentHashMap为什么不允许null值

ConcurrentHashMap为什么不允许null值 一、✅典型解析二、✅要实现一个HashMap怎么做2.1 ✅需要考虑以下几个方面2.2 ✅基于数组和链表的HashMap实现Demo2.3 ✅扩容后如何解决链表长度过长的问题 三、✅拓展知识仓3.1 ✅在多线程环境下如何保证数据的正确性和性能3.2 ✅那如何在…

git 的安装

git 的安装 在我们开始使用 Git 前&#xff0c;需要将它安装在我们的电脑上。即便已经安装&#xff0c;最好将它升级到最新的版本。 我们可以通过软件包或者其它安装程序来安装&#xff0c;或者下载源码编译安装。 本文只介绍通过在 windows 上安装软件包的方式&#xff0c;其…

vue Element Plus Cascader级联选择器点击标签选中复选框

element-plus原功能 element-plus的Cascader级联选择器点击标签时是不会选中复选框的&#xff0c;我们想要实现点击标签时也能选中复选框这个效果&#xff0c;那么就要用到一些原生的方法 实现效果 mounted() {// Cascader 级联选择器: 点击文本就让它自动点击前面的input就可…

Vue 自定义仿word表单录入之日期输入组件

因项目需要&#xff0c;要实现仿word方式录入数据&#xff0c;要实现鼠标经过时才显示编辑组件&#xff0c;预览及离开后则显示具体的文字。 鼠标经过时显示 正常显示及离开时显示 组件代码 <template ><div class"paper-input flex flex-col border-box "…

JAVA基础学习笔记-day17-反射

JAVA基础学习笔记-day17-反射 1. 反射(Reflection)的概念1.1 反射的出现背景1.2 反射概述1.3 Java反射机制研究及应用1.4 反射相关的主要API1.5 反射的优缺点 2. 理解Class类并获取Class实例2.1 理解Class2.1.1 理论上2.1.2 内存结构上 2.2 获取Class类的实例(四种方法)2.3 哪些…

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin

Android基于Matrix绘制PaintDrawable设置BitmapShader&#xff0c;以手指触点为中心显示原图像圆图&#xff0c;Kotlin 手指在上面的图上移动&#xff0c;“剪切”出上面图中以手指触点为中心的图&#xff08;半径图&#xff09;&#xff0c;然后在下面的ImageView显示。 impor…