力扣日记11.25-【二叉树篇】对称二叉树

力扣日记:【二叉树篇】对称二叉树

日期:2023.11.25
参考:代码随想录、力扣

101. 对称二叉树

题目描述

难度:简单

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:
在这里插入图片描述

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

示例 2:
在这里插入图片描述

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

提示:

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

进阶:你可以运用递归和迭代两种方法解决这个问题吗?

题解

/**
 * 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 {
#define SOLUTION 1
public:
#if SOLUTION == 0
    bool isSymmetric(TreeNode* root) {
        /* // 错误的做法
        // 示例1:前:1234243, 中:3241423, 后:3424321,层:1223443
        // 示例2:中:12323,层:12233
        // 层序遍历不行,只能中序遍历
        // 使用栈,元素先进栈,遇到相同的则弹出
        // 还是不能用值来判断是否对称....如果树上节点的值都是相等的,那就无法判断了...
        stack<int> st_check;  // 用来判断
        // 中序遍历:左中右
        // 对于中序遍历,访问和处理并不是同步进行的。而是先访问到最底层的左节点,再开始处理(入栈判断)
        
        // 使用 cur 指针 先进行访问(遍历)
        // if (root == NULL) return true;
        stack<TreeNode*> st;    // 用来遍历
        TreeNode* cur = root;
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) { // 指针访问节点,先遍历到最底层
                st.push(cur);   // 将cur入栈
                cur = cur->left;    // 左
            } else { // 处理
                cur = st.top();   // 中 (处理:放入result数组)
                st.pop();
                if (cur != root) {  // 根节点不入栈判断
                    if (st_check.empty() || st_check.top() != cur->val) st_check.push(cur->val);    // 空或不相等则入栈
                    else st_check.pop();    // 相同则弹出
                }
                cur = cur->right;   // 右 (如果右节点不为空,则在下次循环把右节点入栈;否则从栈中弹出顶部节点)
            }
        }
        return st_check.empty(); 
        */
    }
#elif SOLUTION == 1     // 递归遍历
    /*
        思路:判断二叉树是否对称 -> 通过判断二叉树能否左右翻转
        分别比较外侧与内侧是否相等,即左节点的外侧(左孩子)需与对应右节点的外侧(右孩子)相等,内测同理
        采用的遍历方式为后序遍历 -> 后序:左右中 -> 在左右子树都判断好是否能左右翻转后,再将信息传递到父节点(中),中节点作为左孩子或右孩子又继续向上传递
    */
    bool compare(TreeNode* left, TreeNode* right) { 
        // 递归三要素1:参数与返回值:参数为当前层的左节点和对应右节点,返回值为两者的子树能否相互翻转(注意是子树,不包括自身,尽管只有当左和对应右节点相等才有继续比较的必要)
        // 递归三要素2:终止条件:
        // 1) 左右都为空:返回true
        if (left == NULL && right == NULL)  return true;
        // 2) 左为空右不为空 或 左不为空右为空:返回false
        else if ((left != NULL && right == NULL) || (left == NULL && right != NULL))    return false;
        // 3) 左右不为空且左右值不相等
        else if (left->val != right->val)   return false;
        // 递归三要素3:处理逻辑:如果左右值相等,则递归向下判断
        else {                                                  // 由此可见:左右子树均为后序遍历
            // 外侧:
            bool outside = compare(left->left, right->right);   // 左子树:左、 右子树:右
            // 内侧:
            bool inside = compare(left->right, right->left);    // 左子树:右、 右子树:左
            // 将外侧内侧的比较结果向上传递(给中节点)
            bool isSame = outside && inside;                    // 左子树:中、 右子树:中 (逻辑处理)
            return isSame; // 当外侧和内侧的子节点都分别相等,则当前left和right的子树是可以翻转的
        }
    }
    bool isSymmetric(TreeNode* root) {
        return compare(root->left, root->right);
    }

#elif SOLUTION == 2 // 迭代法(队列)
    bool isSymmetric(TreeNode* root) {
        // 思路:
        // 遍历:将左侧节点和对应右侧节点成对放入队列;
        // 处理:再在弹出时成对弹出比较是否相等,相等则继续遍历子节点,否则终止
        queue<TreeNode*> q;
        if (root != nullptr) {  // 先把根节点的左右节点放入队列
            q.push(root->left);
            q.push(root->right);
        }
        while (!q.empty()) {
            // 成对弹出
            TreeNode* leftSide = q.front();     q.pop();
            TreeNode* rightSide = q.front();    q.pop();
            // 比较
            if (!leftSide && !rightSide) continue; // 左右都为空(没有子节点,则继续弹出)
            // 左右有一个为空 或 左右都不为空但不相等,则肯定不对称,返回false
            else if (!leftSide || !rightSide || (leftSide->val != rightSide->val)) return false;
            // 如果相等,则继续遍历,将子节点入队列
            q.push(leftSide->left);
            q.push(rightSide->right); // 注意要成对:左的左 与 右的右
            q.push(leftSide->right);
            q.push(rightSide->left);    // 左的右 与 右的左
        }
        return true;
    }
#elif SOLUTION == 3 // 迭代法(栈)
    bool isSymmetric(TreeNode* root) {
        // 思路与队列类似,也是成对入栈、成对弹出、成对比较(队列更好理解……)
        stack<TreeNode*> st;
        if (root != nullptr) {  // 先把根节点的左右节点放入队列
            st.push(root->left);
            st.push(root->right);
        }
        while (!st.empty()) {
            // 成对弹出
            TreeNode* rightSide = st.top();  st.pop();
            TreeNode* leftSide = st.top();   st.pop();     
            // 比较
            if (!leftSide && !rightSide) continue; // 左右都为空(没有子节点,则继续弹出)
            // 左右有一个为空 或 左右都不为空但不相等,则肯定不对称,返回false
            else if (!leftSide || !rightSide || (leftSide->val != rightSide->val)) return false;
            // 如果相等,则继续遍历,将子节点入队列
            st.push(leftSide->left);
            st.push(rightSide->right); // 注意要成对:左的左 与 右的右
            st.push(leftSide->right);
            st.push(rightSide->left);    // 左的右 与 右的左
        }
        return true;
    }
#endif
};

复杂度

时间复杂度:
空间复杂度:

思路总结

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

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

相关文章

操作无法完成错误0x0000709的解决办法,解决0x0000709错误

操作无法完成错误0x0000709是一种常见的Windows错误。这篇文章将带大家了解错误的原因&#xff0c;并提供一些解决该问题的方法&#xff0c;希望能够帮助大家解决0x0000709错误问题。 操作系统错误是我们在使用电脑时经常遇到的问题之一。其中之一就是操作无法完成错误0x000070…

Redis-主从与哨兵架构

Jedis使用 Jedis连接代码示例&#xff1a; 1、引入依赖 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version> </dependency> 2、访问代码 public class JedisSingleTe…

超详细的Python+requests+unittest+excel接口自动化测试框架教程

一、框架结构 工程目录 在这我也准备了一份软件测试视频教程&#xff08;含接口、自动化、性能等&#xff09;&#xff0c;需要的可以直接在下方观看&#xff0c;或者直接关注VX公众号&#xff1a;互联网杂货铺&#xff0c;免费领取 软件测试视频教程观看处&#xff1a; 软件测…

ArcGis如何用点连线?

这里指的是根据已有坐标点手动连线&#xff0c;类似于mapgis中的“用点连线”&#xff0c;线的每个拐点是可以自动捕捉到坐标点的&#xff0c;比直接画精确。 我也相信这么强大的软件一定可以实现类似于比我的软件上坐标时自动生成的线&#xff0c;但是目前我还没接触到那里&a…

lv11 嵌入式开发 GPIO实验 9

目录 1 简介 1.1 GPIO 2 LED实验步骤 2.1 通过电路原理图分析LED的控制逻辑 2.2 通过电路原理图查找LED与Exynos4412的连接关系 2.3 通过数据手册分析GPIO中哪些寄存器可以控制LED 2.4 通过程序去操控对应的寄存器完成对LED的控制 2.4.1 使用寄存器写入…

SpringBoot:邮件发送

官网文档&#xff1a;39. Sending Email (spring.io)。 Sending Email Spring框架提供了JavaMailSender实例&#xff0c;用于发送邮件。 如果SpringBoot项目中包含了相关的启动器&#xff0c;那么就会自动装配一个Bean实例到项目中。 在SpringBoot项目中引入如下Email启动器&a…

十大排序之计数排序、桶排序、基数排序(详解)

文章目录 &#x1f412;个人主页&#x1f3c5;算法思维框架&#x1f4d6;前言&#xff1a; &#x1f380;计数排序 时间复杂度O(nk)&#x1f387;1. 算法步骤思想&#x1f387;2.动画实现&#x1f387; 3.代码实现 &#x1f380;桶排序&#x1f387;1. 算法步骤思想&#x1f38…

activiti流程变量操作api

文章目录 runtimeServicetaskServicedelegateTask测试绘制流程图启动流程runtimeService&taskService查询变量runtimeService&taskService设置变量 runtimeService // ## runtimeService操作的都是executionId runtimeService.startProcessInstanceByKey(processDefin…

ACL权限

ACL权限 目录&#xff1a; 1. 什么是ACL 2. 操作步骤 1. 什么是ACL ACL是Access Control List的缩写&#xff0c;即访问控制列表 每个项目成员在有一个自己的项目目录&#xff0c;对自己的目录有完全权限 项目组中的成员对项目目录也有完全权限 其他人对项目目录没有…

互联网时代的身份标识有哪些?

在互联网时代&#xff0c;我们的在线活动几乎都与IP地址相关。无论是浏览网页、观看视频&#xff0c;还是进行在线交易和沟通交流&#xff0c;我们的设备都会分配到一个独特的IP地址。然而&#xff0c;你可能并未意识到的是&#xff0c;IP地址不仅标识了我们在网络中的身份&…

MySQL 索引相关问题,建议搭建好环境,真实操作一下索引应用到的各种场景

文章目录 什么是 B-tree 和 Btree &#xff1f;B-Tree 和 BTree的区别&#xff1f;MySQL 联合唯一索引是BTree&#xff0c;会带来什么原则&#xff1f;主键索引和单字段唯一索引有什么区别吗什么是 聚簇索引和非聚簇索引 &#xff1f;创建一个三百万数据量的表格&#xff0c;方…

HCIP-七、IS-IS 综合实验

七、IS-IS 综合实验 实验拓扑实验需求及解法1.如图所示&#xff0c;配置所有路由器的接口IP地址。2.运行IS-IS&#xff0c;进程号13.IS-IS优化4.路径优化 实验拓扑 实验需求及解法 本实验模拟IS-IS综合网络&#xff0c;完成以下需求&#xff1a; 1.如图所示&#xff0c;配置所…

Acrel-2000电力监控系统在上海大世界保护修缮工程项目中的应用

摘要&#xff1a;安科瑞生产厂家1876150/-6237黄安南 介绍上海大世界电力监控系统&#xff0c;采用智能电力仪表采集配电现场的各种电参量和开关信号。系统采用现场就地组网的方式&#xff0c;组网后通过现场总线通讯并远传至后台&#xff0c;通过Acrel-2000型电力监控系统实现…

Matplotlib图形配置与样式表_Python数据分析与可视化

Matplotlib图形配置与样式表 配置图形修改默认配置rcParams样式表 Matplotlib的默认图形设置经常被用户诟病。虽然2.0版本已经有了很大改善&#xff0c;但是掌握自定义配置的方法可以让我们打造自己的艺术风格。 配置图形 我们可以通过修个单个图形配置&#xff0c;使得最终图…

搜索引擎语法

演示自定的Google hacking语法&#xff0c;解释含意以及在渗透过程中的作用 Google hacking site&#xff1a;限制搜索范围为某一网站&#xff0c;例如&#xff1a;site:baidu.com &#xff0c;可以搜索baidu.com 的一些子域名。 inurl&#xff1a;限制关键字出现在网址的某…

【数据分享】我国12.5米分辨率的坡度数据(免费获取)

地形数据&#xff0c;也叫DEM数据&#xff0c;是我们在各项研究中最常使用的数据之一。之前我们分享过源于NASA地球科学数据网站发布的12.5米分辨率DEM地形数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff0c;这个DEM数据的优点是精度高。 基于DEM地形数据&…

【OpenGauss源码学习 —— 执行算子(Merge Join 算子)】

执行算子&#xff08;Merge Join 算子&#xff09; 连接算子Merge Join 算子ExecInitMergeJoin 函数MergeJoin 结构体 ExecMergeJoin 函数MergeJoinState 结构体 ExecEndMergeJoin 函数 总结 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重…

阿里云windwos 安装oracle数据库,外部用工具连接不上,只能在服务器本机通过127.0.0.1 连接

1. 首先检查阿里云服务器安全组端口是否开放 oracle 数据库端口 2. 其次找到oracle 安装的目录&#xff0c;打开这俩个文件&#xff0c;将localhost 修改为 服务器本机名称 3.重启oracle 监听服务&#xff0c;就可以连接了

新手如何买卖基金,基金投资基础入门

一、教程描述 本套基金教程&#xff0c;大小2.50G&#xff0c;共有13个文件。 二、教程目录 第01课&#xff1a;基金入门&#xff0c;学会投资其实不难.mp4 第02课&#xff1a;基金分类&#xff0c;琳琅满目清清楚楚.mp4 第03课&#xff1a;以稳取胜&#xff0c;稳健基金稳…

程序的编译与链接(详解)

程序的编译与链接 本章内容如下&#xff1a; 1:程序的翻译环境与执行环境的介绍 2:详解程序的翻译环境(编译链接) 2.1预处理阶段干了啥2.2编译阶段干了啥2.3汇编阶段干了啥2.4链接阶段干了啥 3:预处理详解 预定义符号的介绍#define 的介绍(宏与标识符号)#与##的介绍宏与函数…