相同的树及延伸题型(C语言详解版)

从LeetCode 100和101看二叉树的比较与对称性判断

今天要讲的是leetcode100.相同的树,并且本文章还会讲到延伸题型leetcode101.对称二叉树。本文章编写用的是C语言,大家主要是学习思路,学习过后可以自己点击链接测试,并且做一些对应的生题,现在就让我们开始吧!

一、题目简介

LeetCode 100:相同的树

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入:p = [1,2,3], q = [1,2,3]
输出:true

示例 2:

输入:p = [1,2], q = [1,null,2]
输出:false

示例 3:

输入:p = [1,2,1], q = [1,1,2]
输出:false

提示:

  • 两棵树上的节点数目都在范围 [0, 100] 内
  • -104 <= Node.val <= 104

LeetCode 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

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

二、思路详解

题目一:LeetCode 100(相同的树)

1. 问题分析

这道题里有一个小坑,如果我们单纯只通过遍历来比对是否相等的话,是无法保证二叉树的结构相同的,仅仅只能保证该颗二叉树所包含的节点数值是一致的,但是我们将一颗树分为多个部分来比对就会方便很多,将两棵树对应的左子树与左子树比对,右子树和右子树比对。

2. 解题思路

我们可以使用递归的方法来解决这个问题。递归的基本思路如下:

  • 如果两个节点都为空,返回 true

  • 如果一个节点为空而另一个不为空,返回 false

  • 如果两个节点的值不同,返回 false

  • 递归地比较左子树和右子树。

3. C语言实现
#include <stdbool.h>

// 定义二叉树节点结构
typedef struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

// 递归函数,比较两个节点
bool isSameTree(TreeNode* p, TreeNode* q) {
    // 如果两个节点都为空,返回true
    if (p == NULL && q == NULL) {
        return true;
    }
    // 如果一个为空,另一个不为空,返回false
    if (p == NULL || q == NULL) {
        return false;
    }
    // 如果两个节点的值不同,返回false
    if (p->val != q->val) {
        return false;
    }
    // 递归比较左子树和右子树
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

题目二:LeetCode 101(对称二叉树)

1. 问题分析

这道题与上一道题(LeetCode 100:相同的树)是很相似,但有两个关键的不同点:

  1. 参数不同:这道题只传入一个根节点,即只有一棵树。

  2. 判断条件不同:这道题要求判断的是对称二叉树,即镜像相同。具体来说,左子树的左节点应该与右子树的右节点相同,左子树的右节点应该与右子树的左节点相同。

2. 解题思路

为了解决上述两个不同点,我们可以通过构造一个新的函数来实现将一棵树“一分为二”,再对两侧的左右子树进行比较。递归的基本思路如下:

  1. 递归终止条件

    • 如果两个节点都为空,返回 true,表示这部分是镜像对称的。

    • 如果一个节点为空而另一个不为空,返回 false,表示这部分不对称。

  2. 递归逻辑

    • 如果两个节点的值相同,继续递归比较左子树的左节点与右子树的右节点,以及左子树的右节点与右子树的左节点。

    • 如果两个节点的值不同,直接返回 false

3. C语言实现
#include <stdbool.h>

// 定义二叉树节点结构
typedef struct TreeNode {
    int val;                     // 节点的值
    struct TreeNode *left;       // 指向左子节点的指针
    struct TreeNode *right;      // 指向右子节点的指针
} TreeNode;

// 辅助函数:检查两个节点是否镜像对称
bool check(struct TreeNode* p, struct TreeNode* q) {
    // 如果两个节点都为空,说明这部分是镜像对称的
    if (p == NULL && q == NULL) {
        return true;
    }
    // 如果一个为空,另一个不为空,说明这部分不对称
    if (p == NULL || q == NULL) {
        return false;
    }
    // 如果两个节点的值相同,继续递归检查子节点
    if (p->val == q->val) {
        // 递归检查左子树的左节点与右子树的右节点
        // 以及左子树的右节点与右子树的左节点
        return check(p->left, q->right) && check(p->right, q->left);
    }
    // 如果两个节点的值不同,直接返回false
    return false;
}

// 主函数:判断整棵树是否对称
bool isSymmetric(struct TreeNode* root) {
    // 从根节点开始,调用辅助函数检查整棵树是否对称
    return check(root, root);
}
4.迭代法(拓展)

为了判断一棵二叉树是否对称,我们还可以使用层次遍历(BFS)。由于二叉树的结构特性,我们无法直接通过自身的遍历来实现层次遍历,因此需要借助一个辅助数据结构——队列。队列可以帮助我们逐层比较左右子树的节点,确保对称性。

#include <stdbool.h>

// 定义二叉树节点结构
typedef struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

// 使用迭代方法(层次遍历)判断二叉树是否对称
bool isSymmetric(struct TreeNode* root) {
    // 如果根节点为空,直接返回 true(空树是对称的)
    if (root == NULL) return true;

    // 使用数组模拟队列
    struct TreeNode* queue[1000];
    // head 和 tail 分别指向队列的头部和尾部
    int head = 0, tail = 0;

    // 将根节点的左右子树加入队列
    queue[tail++] = root->left;
    queue[tail++] = root->right;

    // 循环结束条件:队列为空(head == tail)
    while (head != tail) {
        // 从队列中取出两个节点进行比较
        struct TreeNode* leftNode = queue[head++];
        struct TreeNode* rightNode = queue[head++];

        // 如果一个节点为空而另一个不为空,说明不对称,返回 false
        if (leftNode == NULL && rightNode != NULL) return false;
        if (leftNode != NULL && rightNode == NULL) return false;

        // 如果两个节点都为空,跳过本轮循环,继续下一对节点的比较
        if (leftNode == NULL && rightNode == NULL) continue;

        // 如果两个节点的值不相等,说明不对称,返回 false
        if (leftNode->val != rightNode->val) return false;

        // 将左节点的左子节点和右节点的右子节点加入队列
        queue[tail++] = leftNode->left;
        queue[tail++] = rightNode->right;

        // 将左节点的右子节点和右节点的左子节点加入队列
        queue[tail++] = leftNode->right;
        queue[tail++] = rightNode->left;
    }

    // 如果队列为空且没有发现不对称的情况,返回 true
    return true;
}

好啦,今天的leetcode每日一题就到这里啦,欢迎大家点赞收藏,一起进步,我们明天见!

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

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

相关文章

微信小程序-点餐(美食屋)02开发实践

目录 概要 整体架构流程 &#xff08;一&#xff09;用户注册与登录 &#xff08;二&#xff09;菜品浏览与点餐 &#xff08;三&#xff09;订单管理 &#xff08;四&#xff09;后台管理 部分代码展示 1.index.wxml 2.list.wxml 3.checkout.wxml 4.detail.wxml 小结优点 概要…

计算机工程:解锁未来科技之门!

计算机工程与应用是一个充满无限可能性的领域。随着科技的迅猛发展&#xff0c;计算机技术已经深深渗透到我们生活的方方面面&#xff0c;从医疗、金融到教育&#xff0c;无一不在彰显着计算机工程的巨大魅力和潜力。 在医疗行业&#xff0c;计算机技术的应用尤为突出。比如&a…

OS Copilot功能测评:智能助手的炫彩魔法

简介&#xff1a; OS Copilot 是一款融合了人工智能技术的智能助手&#xff0c;专为Linux系统设计&#xff0c;旨在提升系统管理和运维效率。本文详细介绍了在阿里云ECS实例上安装和体验OS Copilot的过程&#xff0c;重点评测了其三个核心参数&#xff1a;-t&#xff08;模式…

随机变量的变量替换——归一化流和直方图规定化的数学基础

变量替换是一种在统计学和数学中广泛应用的技术&#xff0c;它通过定义新的变量来简化问题&#xff0c;使得原本复杂的随机变量变得更加容易分析。 变量替换的公式&#xff0c;用于将一个随机变量 X X X 的概率密度函数 f X f_X fX​ 转换为其经过函数 g g g 变换后的随机变…

新电脑安装系统找不到硬盘原因和解决方法来了

有不少网友反馈新电脑采用官方u盘方式装win10或win100出现找不到硬盘是怎么回事&#xff1f;后来研究半天发现是bios中开启了rst(vmd)模式。如果关闭rst模式肯定是可以安装的&#xff0c;但这会影响硬盘性能&#xff0c;有没有办法解决开启rst模式的情况安装win10或win11呢&…

Maui学习笔记-SignalR简单介绍

SignalR是ASP.NET Core中的一个库,支持服务器与其连接的客服端之间的双象通信,它允许服务器立即将更新的消息推送到客服端,而不是要求客户端轮询服务器来获取更新 创建项目 使用SignalR在服务器实时发送消息给客服端,客服端拿到消息后在UI页面更新 首先创建一个Web API项目 …

接口(完)

大家好&#xff0c;今天我们着重来总结一下接口的知识&#xff0c;并且将接口和抽象类的区别罗列一下&#xff0c;帮助我们更好的认识抽象类和接口。 2.7 抽象类和接口的区别. 抽类和接口都是Java中多态的常见使用方式,都需要重点掌握,同时又要认清两者的区别(重要!!&#xf…

机器学习-线性回归(参数估计之经验风险最小化)

给定一组包含 &#x1d441; 个训练样本的训练集 我们希望能够 学习一个最优的线性回归的模型参数 &#x1d498; 现在我们来介绍线性回归的一种模型参数估计方法&#xff1a;经验风险最小化。 我们前面说过&#xff0c;对于标签 &#x1d466; 和模型输出都为连续的实数值&…

77,【1】.[CISCN2019 华东南赛区]Web4

有句英文&#xff0c;看看什么意思 好像也可以不看 进入靶场 点击蓝色字体 我勒个豆&#xff0c;百度哇 所以重点应该在url上&#xff0c;属于任意文件读取类型 接下来该判断框架了 常见的web框架如下 一&#xff0c;Python 框架 1.Flask URL 示例 1&#xff1a;http://…

c语言中的数组(上)

数组的概念 数组是⼀组相同类型元素的集合&#xff1b; 数组中存放的是1个或者多个数据&#xff0c;但是数组元素个数不能为0。 数组中存放的多个数据&#xff0c;类型是相同的。 数组分为⼀维数组和多维数组&#xff0c;多维数组⼀般⽐较多⻅的是⼆维数组。 数组创建 在C语言…

景联文科技加入AIIA联盟数据标注分委会

2025年1月16日&#xff0c;中国人工智能产业发展联盟&#xff08;简称AIIA&#xff09;数据委员会数据标注分委会&#xff08;以下简称“分委会”&#xff09;正式成立。景联文科技成为第一批AIIA联盟数据标注分委会委员单位。 数据标注分委会的成立旨在搭建数据标注领域产学研…

[笔记] 极狐GitLab实例 : 手动备份步骤总结

官方备份文档 : 备份和恢复极狐GitLab 一. 要求 为了能够进行备份和恢复&#xff0c;请确保您系统已安装 Rsync。 如果您安装了极狐GitLab&#xff1a; 如果您使用 Omnibus 软件包&#xff0c;则无需额外操作。如果您使用源代码安装&#xff0c;您需要确定是否安装了 rsync。…

消息队列篇--通信协议篇--AMOP(交换机,队列绑定,消息确认,AMOP实现实例,AMOP报文,帧,AMOP消息传递模式等)

AMQP&#xff08;Advanced Message Queuing Protocol&#xff0c;高级消息队列协议&#xff09;是一种开放的、跨平台的消息传递协议&#xff0c;旨在提供一种标准化的方式在不同的消息代理和客户端之间进行消息传递。AMQP不仅定义了消息格式和路由机制&#xff0c;还规定了如何…

小利特惠源码/生活缴费/电话费/油卡燃气/等充值业务类源码附带承兑系统

全新首发小利特惠/生活缴费/电话费/油卡燃气/等充值业务类源码附带U商承兑系统 安装教程如下 图片:

HTML<hgroup>标签

例子&#xff1a; 使用hgroup元素标记标题和段落是相关的&#xff1a; <hgroup> <h2>Norway</h2> <p>The land with the midnight sun.</p> </hgroup> 定义和用法&#xff1a; 标签<hgroup>用于包围标题和一个或多个<p&g…

14-6-3C++STL的list

&#xff08;一&#xff09;list的插入 1.list.insert(pos,elem);//在pos位置插入一个elem元素的拷贝&#xff0c;返回新数据的位置 #include <iostream> #include <list> using namespace std; int main() { list<int> lst; lst.push_back(10); l…

【2024年终总结】深圳工作生活评测

距离上次写年终总结已经过了一年半了&#xff0c;这一年半中哪怕经历了很多的事情&#xff0c;但是感觉又没发生什么。想写一些骚话&#xff0c;却总觉得自己无法完全表达&#xff0c;便也就这样&#xff0c;静静地记录下这一段时光。 现在是2025年&#xff0c;春节前的时光&am…

前端jquery 实现文本框输入出现自动补全提示功能

git仓库&#xff1a;web_study/some-demos/inputAutoFit at main Cong0925/web_study (github.com) 压缩包&#xff1a;已绑定到指定资源 示例图&#xff1a; 实现说明: 1.首先&#xff0c;html部分设置好相关的定位标签如图&#xff1a; 2.主要函数 3.默认数据

(5)STM32 USB设备开发-USB键盘

讲解视频&#xff1a;2、USB键盘-下_哔哩哔哩_bilibili 例程&#xff1a;STM32USBdevice: 基于STM32的USB设备例子程序 - Gitee.com 本篇为使用使用STM32模拟USB键盘的例程&#xff0c;没有知识&#xff0c;全是实操&#xff0c;按照步骤就能获得一个STM32的USB键盘。本例子是…

java后端之登录认证

基础登录功能&#xff1a;根据提供的用户名和密码判断是否存在于数据库 LoginController.java RestController Slf4j public class LoginController {Autowiredprivate UserService userService;PostMapping("/login")public Result login(RequestBody User user) {…