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

news2024/10/5 23:31:00

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

日期: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
};

复杂度

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

思路总结

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

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

相关文章

【Docker】从零开始:11.Harbor搭建企业镜像仓库

【Docker】从零开始&#xff1a;11.Harbor搭建企业镜像仓库 1. Harbor介绍2. 软硬件要求(1). 硬件要求(2). 软件要求 3.Harbor优势4.Harbor的误区5.Harbor的几种安装方式6.在线安装(1).安装composer(2).配置内核参数,开启路由转发(3).下载安装包并解压(4).创建并修改配置文件(5…

基于51单片机的FM数字收音机系统电路设计

**单片机设计介绍&#xff0c;基于51单片机的FM数字收音机系统电路设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的FM数字收音机系统是一种用于接收和播放FM广播信号的设备&#xff0c;以下是一个基本的电路设…

TCP 三次握手和四次挥手(图解)

TCP 三次握手和四次挥手 建立连接-三次握手 什么是三次握手&#xff1f; 简单来说&#xff1a; 客户端向服务器发送 SYN 报文&#xff0c;请求建立连接。服务器收到 SYN 报文后&#xff0c;回复一个 SYNACK 的报文&#xff0c;表示同意建立连接。客户端收到 SYNACK 报文后&am…

数据结构—小堆的实现

前言&#xff1a;前面我们已经学习了二叉树&#xff0c;今天我们来学习堆&#xff0c;堆也是一个二叉树&#xff0c;堆有大堆有小堆&#xff0c;大堆父节点大于子节点&#xff0c;小堆父节点总小于子节点&#xff0c;我们在学习C语言的时候也有一个堆的概念&#xff0c;那个堆是…

MYSQL基础知识之【创建,删除,选择数据库】

文章目录 前言MySQL 创建数据库使用 mysqladmin 创建数据库使用 PHP脚本 创建数据库 MySQL 删除数据库使用 mysqladmin 删除数据库使用PHP脚本删除数据库 MySQL 选择数据库从命令提示窗口中选择MySQL数据库使用PHP脚本选择MySQL数据库 后言 前言 hello world欢迎来到前端的新世…

电路 buck-boost相关知识

BUCK-BOOST 文章目录 BUCK-BOOST前言一、DC-DC工作模式电容电感特性伏秒积平衡原理 二、BUCK电路三、BOOST电路四、BUCK-BOOST电路总结 前言 最近需要用到buck-boost相关的电路知识&#xff0c;于是便写下这篇文章复习一下。 一、DC-DC 在学习buck-boost电路之前我们先来看一…

python排序算法_归并排序

什么是归并排序&#xff1a; 归并排序是一种基于分治法的排序算法。它的基本思想是将待排序的序列分成若干个子序列&#xff0c;分别进行排序&#xff0c;然后再将已排序的子序列合并成一个有序的序列。 基本思想&#xff1a; 归并排序是用分治思想&#xff0c;分治模式在每一…

基于人工兔算法优化概率神经网络PNN的分类预测 - 附代码

基于人工兔算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于人工兔算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于人工兔优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…

深入解析Selenium动作链:精通点击、拖拽、切换等操作

背景&#xff1a; 一些交互动作都是针对某个节点执行的。比如&#xff0c;对于输入框&#xff0c;我们就调用它的输入文字和清空文字方法&#xff1b;对于按钮&#xff0c;就调用它的点击方法。其实&#xff0c;还有另外一些操作&#xff0c;它们没有特定的执行对象&#xff0…

大模型微调技术

全量微调 部分参数微调 Adaper-Tuning 降维的意义 计算和存储成本去除冗余和噪声—特定任务训练数据有限减少模型复杂度避免过拟合风险适应任务需求过拟合 是指模型在训练数据上表现得很好,但在新的未见过的数据上表现较差的现象模型过于复杂,训练数据量不足等因素引起的 LO…

ubuntu22.04中ros2 安装rosbridge

ros2 启动rosbridge&#xff1a; 要启动ROS2中的rosbridge&#xff0c;需要先安装ROS2的rosbridge_suite软件包。使用以下命令安装&#xff1a; 更新过可忽略 sudo apt-get update安装命令 sudo apt-get install ros--rosbridge-suite 注意&#xff1a; 将替换为正在使用的R…

超实用:通过文字就可以操纵这款AI表格,不需要你懂Excel函数

公众号「架构成长指南」&#xff0c;专注于生产实践、云原生、分布式系统、大数据技术分享。 工具介绍 今天给大家分享超实用的AI表格ChatExcel&#xff0c;这个工具是由北大团队在2022年3月开始开发的AI表格处理神器&#xff0c;上传你的表格后&#xff0c;只需要用文字描述你…

NX二次开发UF_CURVE_ask_int_curves 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_int_curves Defined in: uf_curve.h int UF_CURVE_ask_int_curves(tag_t int_curve_object, int * num_curves, tag_t * * intersection_curves ) overview 概述 Ret…

基于厨师算法优化概率神经网络PNN的分类预测 - 附代码

基于厨师算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于厨师算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于厨师优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

leetCode 226.翻转二叉树 递归 + 非递归 + 前中后序 + 层序遍历 【深度和广度优先遍历】

我的往期文章&#xff1a; leetCode 226.翻转二叉树-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/134613347?spm1001.2014.3001.5501 &#xff08;一&#xff09;递归做法&#xff08;深度&#xff09; C代码&#xff1a;前序遍历 class Solution { pu…

电力感知边缘计算网关产品设计方案-网关软件设计方案

网关采用网络协议和软件技术在通信网络中针对工业协议、互联网通用协议进行分析和记录,提升工业控制系统环境的安全防护能力。A类和B类网关采用容器技术的软件架构,采用C/S架构软件客户端提供应用软件平台,为管理员提供功能丰富的图形管理控制界面。 因A类和B类网关在产品定…

Loadrunner安装大全

目录 一 、下载篇 二、安装篇 三、破解篇 四、Loadrunner支持哪些操作系统&#xff1f; 五、安装Loadrunner需要满足哪些系统要求&#xff1f; 六、安装Loadrunner时是否需要注意什么问题&#xff1f; 七、安装完成后如何验证Loadrunner是否正常工作&#xff1f; 八、如…

“升级图片质量:批量提高或缩小像素,赋予图片全新生命力!“

如果你想让你的图片更加清晰、更加美观&#xff0c;或者符合特定的像素要求&#xff0c;那么现在有一个好消息要告诉你&#xff01;我们推出了一款全新的图片处理工具&#xff0c;可以帮助你批量提高或缩小图片像素&#xff0c;让你的图片焕发出新的生机&#xff01; 第一步&a…

栈和队列OJ题目——C语言

目录 LeetCode 20、有效的括号 题目描述&#xff1a; 思路解析&#xff1a; 解题代码&#xff1a; 通过代码&#xff1a; LeetCode 225、用队列实现栈 题目描述&#xff1a; 思路解析&#xff1a; 解题代码&#xff1a; 通过代码&#xff1a; LeetCode 232、用栈…

基于微信小程序的员工宿舍报修系统

项目介绍 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时…