【手撕数据结构】二叉树oj题

news2024/11/15 13:36:52

目录

  • 单值二叉树
    • 题目描述
    • 题目思路及代码
  • 相同的树
    • 题目描述
    • 题目思路及代码
  • 对称二叉树
    • 题目描述
    • 题目思路及代码
  • 另一棵树的子树
    • 题目描述
    • 题目思路及代码
  • 二叉树的前序遍历
    • 题目描述
    • 题目思路及代码
  • 二叉树的构建与遍历
    • 题目描述
    • 题目思路及代码

单值二叉树

题目描述

在这里插入图片描述

题目思路及代码

  • 这道题的要求就是每个节点的值都要相等
  • 如果我们想要整个二叉树相等,就要让二叉树的子树都相等。想要先判断子树,我们就用先序遍历。先遍历左子树,然后遍历右子树。然后将其每个子树的父节点和他们的孩子节点的值进行比较是否相等。当所有左子树和右子树都比较完了,那么整颗二叉树就是一颗单值二叉树。
  • 如果当左右孩子的值其中一个不等于父节点的值,返回false
  • -如果遇到节点为NULL,说明从根节点到该节点的值都相同

注意:
在这里插入图片描述
下面是代码:

/**
 - Definition for a binary tree node.
 - struct TreeNode {
 -     int val;
 -     struct TreeNode *left;
 -     struct TreeNode *right;
 - };
 */
 typedef struct TreeNode TreeNode;
bool isUnivalTree(struct TreeNode* root) {
    if(root == NULL)
    {
        return true;
    }
    if(root->left && root->left->val != root->val || root->right && root->right->val != root->val)
    {
        return false;
    }
    return isUnivalTree(root->left) && isUnivalTree(root->right);
}

相同的树

题目描述

在这里插入图片描述

题目思路及代码

  • 我们不光要求值相同,结构也要相同,也就是节点的位置也相同。
  • 那我们就可以先从结构入手,如果两颗二叉树都是空树,那么他们一定结构并且值相同。直接返回true
  • 如果两颗二叉树其中有一个不是空树,而另一个事空树,结构肯定不同,直接返回false。
  • 结构判断完了,就判断值,两个指针分别从两颗二叉树的祖宗节点同时开始遍历他们的左右子树,如果A二叉树和B二叉树的左子树节点有一个节点不相同返回false,如果左子树节点都相同,但是右子树节点不相同返回false。
    在这里插入图片描述
    代码如下:
 typedef struct TreeNode TreeNode;
bool isSameTree(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 false;
    }
    return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
  • 如果左子树或右子树一直没找到不相同的节点,直到空节点两个肯定结构和值相同,说明左子树或右子树是一颗相同的二叉树就返回true。也就是第一个if

对称二叉树

题目描述

在这里插入图片描述

题目思路及代码

  • 是不是和上一道相同的二叉树有异曲同工之处。
  • 就是把A二叉树的左子树节点与B二叉树的右子树节点比较,把A二叉树的右子树节点和B二叉树的左子树节点比较即可。就是改变了比较位置。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
 typedef struct TreeNode TreeNode;
bool isSameTree(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 false;
    }
    return isSameTree(p->left, q->right) && isSameTree(p->right, q->left);
}


bool isSymmetric(struct TreeNode* root) {
  return isSameTree(root->left, root->right);
}



  • 可以看到就是你走左,我走右。你走右,我走左
    在这里插入图片描述

另一棵树的子树

题目描述

在这里插入图片描述

题目思路及代码

  • 如果想要找另一个二叉树是否为这一个二叉树的子树,那么就要先找到与那个二叉树祖宗节点相等的节点。然后再两个二叉树同时递归比较。
  • 如果节与子树的祖宗节点相同,那么直接调用判断两个数是否相等的方法进行比较,不用再往子树递归。
  • 同理,如果第一个节点不和子树祖宗节点相等,那就先递归左子树,在左子树中找是否有相等的节点。如果没有,就递归右子树寻找
  • 如果递归遍历左右子树过程中,遍历到节点为NULL,说明左子树或右子树遍历完没找到与子树相同的节点。则左或右子树中没有匹配的节点。直接返回false。

在这里插入图片描述

typedef struct TreeNode TreeNode;
bool isSameTree(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 false;
    }
    return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
   if(root == NULL)
   {
    return false;
   }
   if(isSameTree(root,subRoot))
   {
    return true;
   }
   return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
 }
  • 这里||运算连接左右子树递归,就是左子树可能找不到,但是右子树可能找到。并且如果左子树找到了,右子树就不用找了。

二叉树的前序遍历

题目描述

在这里插入图片描述

题目思路及代码

  • 注意读题,我们是需要把二叉树的节点,按前序遍历的顺序存储在一个数组中。
  • 这个数组需要我们自己动态开辟,而如果要知道开辟多大空间,我们就需要二叉树一共有几个节点,这就可以用到链式二叉树讲的求节点个数算法。
  • 在前序遍历递归过程中,我们需要控制数组的下标来决定存储节点的位置,这时候下标最好作为一个参数传递,在每次函数递归开辟函数栈帧的时候,用指针来接受下标,保证形参一定会改变实参,从而影响到上一次递归的函数栈帧的下标发生改变。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
typedef struct TreeNode TreeNode;
int BinaryTreeSize(TreeNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
void _preorderTravelsal(TreeNode* root, int *arr,  int* pi)
{
    if(root == NULL)
    {
        return;
    }
    arr[(*pi)++] = root->val;
    _preorderTravelsal(root->left, arr, pi);
    _preorderTravelsal(root->right, arr, pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    //先求出二叉树节点个数
    *returnSize = BinaryTreeSize(root);
    //动态开辟空间
    int* returnArr = (int*)malloc(sizeof(int) * (*returnSize));
    //为避免在原函数递归重复开辟空间和调用方法,写一个子函数
    int i = 0;
    _preorderTravelsal(root, returnArr, &i);
    return returnArr;
}
  • 中序遍历和后序遍历一样的思路,把arr[*(pi)++] = root->val,放在递归函数中间或递归函数之后。

二叉树的构建与遍历

题目描述

在这里插入图片描述

题目思路及代码

  • 按题目所说,我们需要将用户输入的先序遍历字符串按先序遍历的方式创建一个二叉树。然后我们再对构建的二叉树进行中序遍历。
  • 这就要看怎么构建了:

第一种构建方式:
在这里插入图片描述

  • 很明显C作为根节点a的右孩子并不满足是一个二叉树。

我们再来看看另一个构建方法:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 按照如果不是构建到空节点就一直按照根左右的顺序,先构建根节点,然后构建左孩子结点,构建到空节点后,空节点不可能作为子树的根节点,返回子树根节点开始构建右孩子节点。从下往上构建子树,最后构建完所以子树就是一颗先序遍历顺序构建的二叉树。

在这里插入图片描述

TreeNode* CreatNode(char* arr, int* pi)
{
    if(arr[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }
    TreeNode* root = buyNode(arr[(*pi)++]);//构建节点
    root->left = CreatNode(arr, pi);
    root->right = CreatNode(arr, pi);
    return root;
}
  • 这里为空节点就回上一次递归开始构建右孩子节点/但是不要忘了将这个遍历先序序列数组的指针后移,便于下一次的访问
  • 我们构建的同时就要开辟空间来存储节点,既然节点这么多。我们不妨封装一个函数来开辟空间存储节点。
TreeNode* buyNode(char x)
{
    TreeNode* newnode = (TreeNode*)malloc(sizeof(TreeNode));
    newnode->val = x;
    newnode->left = newnode->right = NULL;
    return newnode;
}
  • 构建完成就可以中序遍历了.
void InOrder(TreeNode* root)
{
    if(root == NULL)
    {
        return;
    }
    InOrder(root->left);
    printf("%c ",root->val);
    InOrder(root->right);
}

下面是整体代码:

#include<stdio.h>
#include<stdlib.h>
typedef struct TreeNode
{
    char val;
    struct TreeNode* left;
    struct TreeNode* right;
}TreeNode;
TreeNode* buyNode(char x)
{
    TreeNode* newnode = (TreeNode*)malloc(sizeof(TreeNode));
    newnode->val = x;
    newnode->left = newnode->right = NULL;
    return newnode;
}
TreeNode* CreatNode(char* arr, int* pi)
{
    if(arr[*pi] == '#')
    {
        (*pi)++;
        return NULL;
    }
    TreeNode* root = buyNode(arr[(*pi)++]);
    root->left = CreatNode(arr, pi);
    root->right = CreatNode(arr, pi);
    return root;
}
void InOrder(TreeNode* root)
{
    if(root == NULL)
    {
        return;
    }
    InOrder(root->left);
    printf("%c ",root->val);
    InOrder(root->right);
}
int main()
{
    char arr[100];
    scanf("%s", arr);
    //创建二叉树
    int i = 0;
    TreeNode* root = CreatNode(arr, &i);
    InOrder(root);
    return 0;
}

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

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

相关文章

模型 情境领导力

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。灵活变通&#xff0c;因势利导的领导艺术。 1 情境领导力的应用 1.1 软件项目的成功转型 在一家知名的软件开发公司中&#xff0c;有一个由资深工程师李伟领导的团队&#xff0c;负责开发一款新的客…

Mac下的压缩包和Win看到的不一样怎么办 Mac压缩后Win电脑看文件名会乱码

在当今多平台的数字工作环境中&#xff0c;Mac和Windows用户常常需要交换文件&#xff0c;但有时候会遇到一些兼容性问题。特别是在处理压缩文件时&#xff0c;Mac用户创建的压缩包在Windows系统中打开时&#xff0c;常常会遇到文件名乱码的问题。本文将详细讨论“Mac下的压缩包…

基于AI大模型开发上层应用常见的技术栈

基于AI大模型的上层应用开发&#xff0c;技术栈要求通常包括以下几个方面&#xff1a; 编程语言&#xff1a;Python是AI领域的主要编程语言&#xff0c;具有大量的库和框架支持&#xff0c;是大模型开发的首选语言 。TypeScript也是不错的选择&#xff0c;很多模型对外提供类似…

postman学习笔记:从入门到精通

postman入门到精通 一、postman下载安装与更换主题1、下载与安装2、更换主题&#xff08;Themes&#xff09; 二、页面详解1、顶部工具栏2、左侧栏3、中部栏3.1 请求部分页签介绍3.2 响应部分页签介绍 三、管理用例四、设置环境变量和全局变量1、添加环境变量2、添加全局变量 五…

编码666

unicode&#xff0c;将每种语言的每种格式都用一个二进制编码来表示&#xff0c;1到3个字节 问题&#xff1a;1.系统怎么知道是ASCII还是Unicode编码&#xff0c;怎么直到一个字符是一字节还是多个字节 2.很多字符需要2字节或更多&#xff0c;存储空间的要求会更高 UTF-8&…

AIGC提示词(3):AI的创造力之谜:相同提示词,不同内容

引言 在这个数字化的时代&#xff0c;人工智能生成内容&#xff08;AIGC&#xff09;已经变得无处不在。想象一下&#xff0c;只需输入几个关键词&#xff0c;AI就能创作出各种内容&#xff0c;无论是文字、图片&#xff0c;还是其他形式。但这里有个有趣的问题&#xff1a;如…

简易计算器(源码+程序)

效果演示&#xff1a; 下载地址&#xff1a; 简易计算器&#xff08;源码程序&#xff09;&#xff1a;https://download.csdn.net/download/wgxds/89696805 vb.net开发安卓软件的方法&#xff1a;[原创]vb.net开发安卓软件的方法_vbnet开发安卓-CSDN博客 免费资源下载&#x…

【系统架构师软考】计算机网络知识(四)

目录 奈奎斯特定理 奈奎斯特速率 ​编辑 香农定理 物联网(IOT) ​编辑 TCP 和 UDP HTTP、HTTPS 和 WebSocket ICMP、IGMP、OSPF协议 SNMP ​编辑 DHCP协议和DNS协议 ​编辑 RAP和ARAP TFTP、FTP和 SFTP POP3, IMAP,SMTP 其他网络协议 无线网络协议 IP地址的格…

【Android】MotionLayout实现动画效果

【Android】MotionLayout实现开场动画 在移动应用开发中&#xff0c;动画不仅仅是美化界面的工具&#xff0c;它更是提升用户体验的关键手段。Android 平台一直以来都提供了丰富的动画框架&#xff0c;但随着应用复杂性的增加&#xff0c;开发者对动画的需求也变得更加复杂和多…

【Navicat最新版简体中文版破解激活永久详细教程】

2024 Navicat Premium最新版简体中文版破解激活永久图文详细教程 1.未安装过的用户可直接跳过该步骤&#xff0c;如果已安装Navicat&#xff0c;记得先卸载干净&#xff0c;防止破解失效&#xff0c;卸载完成后执行补丁压缩包中的Navicat.bat脚本&#xff08;一闪而过表示正常&…

背包问题——分组背包

样题&#xff1a; 枚举第i组选第几个物品 #include <bits/stdc.h> using namespace std; const int N 110; int f[N],w[N][N],v[N][N],s[N];int main() {ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int n,V,cnt 0; cin >> n >> V;for(int i 1; i &…

HTML爱心流星雨

目录 写在前面 完整代码 代码分析 推荐系列 写在后面 写在前面 如何用HTML代码实现爱心流星雨的动态效果&#xff1f;本期博主将带着大家探索神奇的HTML。 完整代码 <!doctype html> <html> <head><meta charset"utf-8"><title&g…

axios取消请求CancelToken的原理解析及用法示例

文章目录 一、axios的实例与请求流程二、CancelToken 的作用三、CancelToken 的实现原理四、取消请求的流程五、CancelToken用法六、利用拦截器取消请求1、axios请求拦截器2、axios响应拦截器3、利用路由导航守卫取消请求 一、axios的实例与请求流程 下图是axios实例属性的简图…

Scrach游戏制作:时机的活儿~(可自改难度)(免费源码)

游戏演示&#xff1a; 这是个时机di活儿~_哔哩哔哩_bilibili 作品制作流程&#xff1a; 自由移动不断切换造型传送&#xff08;碰撞检测&#xff09;火车&&棒球的旋转增加关卡难度游戏结束 1. 自由移动&#xff08;对猫猫编程&#xff09; 自由移动是让角色能够朝上下…

Camtasia 2024 v2024.0.6 for Mac 中文版 屏幕录像视频录制编辑软件

TechSmith Camtasia for Mac 中文版 是一款专业的屏幕录像及视频录制编辑软件。以业界领先的清晰度重新定义了屏幕录制&#xff0c;将屏幕、摄像头、麦克风和系统音频捕获为独立音轨&#xff0c;实现终极控制和灵活性。通过拖放过渡、标注等功能&#xff0c;以及改进的工作流程…

WCT系列(四):BLASTSyncEngine

WCT系列&#xff08;一&#xff09;&#xff1a;WindowContainerTransaction类详解 WCT系列&#xff08;二&#xff09;&#xff1a;SyncTransactionQueue类详解 WCT系列&#xff08;三&#xff09;&#xff1a;WindowOrganizerController WCT系列&#xff08;四&#xff09;&a…

图片拼图怎么做?4个方法打造具有高级感的拼图作品

被阿勒泰的日落治愈了&#xff0c;旅行中的每一刻都值得珍藏。 这次的阿勒泰之行&#xff0c;我不仅带回了一堆美好的回忆&#xff0c;还有手机里满满的精彩瞬间。从壮丽的山川到静谧的湖泊&#xff0c;从晨曦初现到夜幕降临&#xff0c;每一帧都是大自然的馈赠。但是&#xf…

C++ 设计模式——职责链模式

目录 C 设计模式——职责链模式1. 主要组成成分2. 逐步构建职责链模式步骤1&#xff1a;定义处理者接口步骤2&#xff1a;定义抽象处理者步骤3: 创建具体处理者步骤4: 配置职责链 3. 备忘录模式 UML 图UML 图解析 4. 单纯与非单纯的职责链模式4.1 敏感词过滤器父类4.2 具体过滤…

C++:类的定义、实例化

目录 一、类的定义 1.1 类的定义格式 1.2 访问限定符 1.3 类域 二、实例化 2.1 实例化概念 2.2 对象大小 一、类的定义 1.1 类的定义格式 • class为定义类的关键字&#xff0c;Stack为类的名字&#xff0c;{}中为类的主体&#xff0c;注意类定义结束时后面分号不能省…

设备上的实时自定义手势识别

这篇论文的标题是《On-device Real-time Custom Hand Gesture Recognition》&#xff0c;主要研究了如何在移动设备上实时识别自定义手势。以下是论文的主要内容概述&#xff1a; 摘要&#xff1a; 论文指出现有的手势识别系统大多限于预定义的手势集&#xff0c;但用户和开发…