Day17.一刷数据结构算法(C语言版) 654最大二叉树;617合并二叉树;700二叉搜索树中的搜索;98验证二叉搜索树

        又是破防的一天......


一.654最大二叉树

        又是构造二叉树,昨天大家刚刚做完 中序后序确定二叉树,今天做这个 应该会容易一些, 先看视频,好好体会一下 为什么构造二叉树都是 前序遍历 

        题目链接:最大二叉树

        文章讲解:代码随想录

        视频讲解:又是构造二叉树,又有很多坑!| LeetCode:654.最大二叉树

 1.思路分析

        简单来说,二叉树构建过程如下:

        构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。 

        递归三部曲:

        1)确定递归函数的参数和返回值

        参数传入的是存放元素的数组以及左右边界索引,返回该数组构造的二叉树的头结点,返回类型是指向节点的指针。

struct TreeNode* traversal(int* nums, int left, int right)

         2)确定终止条件

        当左右边界相等或左右颠倒时,返回NULL。

//若左边界大于右边界,返回NULLif(left >= right)return NULL;

        3)确定单层递归的逻辑

        第一步:先要找到数组中最大的值和对应的下标, 最大的值构造根节点,下标用来下一步分割数组。

//找出数组中最大数坐标int maxIndex = left;int i;for(i = left + 1; i < right; i++) {if(nums[i] > nums[maxIndex])maxIndex = i;}//开辟结点struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));//将结点的值设为最大数组数组元素node->val = nums[maxIndex];

        第二步:最大值所在的下标左区间构造左子树。

node->left = traversal(nums, left, maxIndex);

        第三步:最大值所在的下标右区间构造右子树。

node->right = traversal(nums, maxIndex + 1, right);

2.代码详解

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/
struct TreeNode* traversal(int* nums, int left, int right) {//若左边界大于右边界,返回NULLif(left >= right)return NULL;//找出数组中最大数坐标int maxIndex = left;int i;for(i = left + 1; i < right; i++) {if(nums[i] > nums[maxIndex])maxIndex = i;}//开辟结点struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));//将结点的值设为最大数组数组元素node->val = nums[maxIndex];//递归定义左孩子结点和右孩子结点node->left = traversal(nums, left, maxIndex);node->right = traversal(nums, maxIndex + 1, right);return node;
}struct TreeNode* constructMaximumBinaryTree(int* nums, int numsSize){return traversal(nums, 0, numsSize);
}

 二.617合并二叉树

        这次是一起操作两个二叉树了, 估计大家也没一起操作过两个二叉树,也不知道该如何一起操作,可以看视频先理解一下。 优先掌握递归。

        题目链接:合并二叉树

        文章讲解:代码随想录

        视频讲解:一起操作两个二叉树?有点懵!| LeetCode:617.合并二叉树_哔哩哔哩_bilibili

 1.思路分析

        其实和遍历一个树逻辑是一样的,只不过传入两个树的节点,同时操作。

        这道题用哪种遍历都可以,本人以前序为例。

        递归三部曲:

        1)确定递归函数的参数和返回值

        首先要合入两个二叉树,那么参数至少是要传入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。 

struct TreeNode* mergeTrees(struct TreeNode* root1, struct TreeNode* root2)

        2)确定终止条件

        因为是传入了两个树,那么就有两个树遍历的节点root1 和 root2,如果root1 == NULL 了,两个树合并就应该是 root2 了(如果root2也为NULL也无所谓,合并之后就是NULL)。

        反过来如果root2 == NULL,那么两个数合并就是root1(如果root1也为NULL也无所谓,合并之后就是NULL)。

        代码如下:

if (root1 == NULL) return root2; // 如果root1为空,合并之后就应该是root2
if (root2 == NULL) return root1; // 如果root2为空,合并之后就应该是root1

         3)确定单层递归的逻辑

        单层递归的逻辑就比较好写了,这里我们重复利用一下root1这个树,root1就是合并之后树的根节点(就是修改了原来树的结构)。

        那么单层递归中,就要把两棵树的元素加到一起。

root->val=root1->val+root2->val;

        接下来root1 的左子树是:合并root1左子树root2左子树之后的左子树。

        root1 的右子树:是 合并 root1右子树 root2右子树之后的右子树。

        最终t1就是合并之后的根节点。

root->left=mergeTrees(root1->left,root2->left);
root->right=mergeTrees(root1->right,root2->right);
return root;

 2.代码详解

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/
struct TreeNode* mergeTrees(struct TreeNode* root1, struct TreeNode* root2) {if(root1==NULL) return root2;if(root2==NULL) return root1;struct TreeNode* root=(struct TreeNode*)malloc(sizeof(struct TreeNode));root->val=root1->val+root2->val;root->left=mergeTrees(root1->left,root2->left);root->right=mergeTrees(root1->right,root2->right);return root;
}

 三.700二叉搜索树中的搜索

        递归和迭代 都可以掌握以下,因为本题比较简单, 了解一下 二叉搜索树的特性

        题目链接:二叉搜索树中的搜索

        文章讲解: 代码随想录

        视频讲解:不愧是搜索树,这次搜索有方向了!| LeetCode:700.二叉搜索树中的搜索

1.思路分析

        本题,其实就是在二叉搜索树中搜索一个节点。那么我们来看看应该如何遍历。

        递归三部曲:

        1)确定递归函数的参数和返回值

        递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。

        代码如下:

struct TreeNode* searchBST(struct TreeNode* root, int val)

         2)确定终止条件

        如果root为空,或者找到这个数值了,就返回root节点。

if (root == NULL || root->val == val) return root;

        3) 确定单层递归的逻辑

        看看二叉搜索树的单层递归逻辑有何不同。

        因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。

        如果root->val 大于val,搜索左子树,如果root->val 小于 val,就搜索右子树,最后如果都没有搜索到,就返回NULL。

struct TreeNode* result = NULL;
if (root->val > val) result = searchBST(root->left, val);
if (root->val < val) result = searchBST(root->right, val);
return result;

        很多人写递归函数的时候习惯直接写searchBST(root->right, val),却忘了递归函数还有返回值。

        递归函数的返回值是什么? 是左子树如果搜索到了val,要将该节点返回。 如果不用一个变量将其接住,那么返回值不就没了。

        所以要result = searchBST(root->right, val);并在最后return result

2.代码详解

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/
struct TreeNode* searchBST(struct TreeNode* root, int val) {if (root == NULL || root->val == val) return root;struct TreeNode* result = NULL;if (root->val > val) result = searchBST(root->left, val);if (root->val < val) result = searchBST(root->right, val);return result;
}

 四.98验证二叉搜索树

        遇到 搜索树,一定想着中序遍历,这样才能利用上特性。 

        但本题是有陷阱的,可以自己先做一做,然后在看题解,看看自己是不是掉陷阱里了。这样理解的更深刻。

        题目链接:验证二叉搜索树

        文章讲解:代码随想录

        视频讲解:你对二叉搜索树了解的还不够! | LeetCode:98.验证二叉搜索树

 1.思路分析

        要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列。

        有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。

        这道题目比较容易陷入两个陷阱:

  • 陷阱1

        不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了

        我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点

        例如: [10,5,15,null,null,6,20] 这个case:

 

        节点10大于左节点5,小于右节点15,但右子树里出现了一个6 这就不符合了! 

  • 陷阱2

        样例中最小节点可能是int的最小值,如果这样使用最小的int来比较也是不行的。

        此时可以初始化比较元素为longlong的最小值。

        (不过本人写的代码并没有考虑longlong的情况,所以如果你比较顾虑,可以自行修改)

        递归三部曲:

        1)确定递归函数的参数和返回值

bool isValid(struct TreeNode* root,struct TreeNode** pre)

(悄悄话:其中,pre为用来记录前一个节点的指针的指针,我一开始本想当作全局变量放在函数前面。测试的时候没问题,但是提交的时候,面对{0}的输入,输出错误,也不知道怎么回事。如果你平时有认真看我的博客的话,你会发现我上一次也用了指针的指针来代替全局变量,错误的具体原因我也不太清楚,这也是我今天破防的原因。我回头再研究一下。我破防的另一个原因是,在第三题,我遍历的时候脑袋短路了,当时就是不明白为什么在最后要写返回值......)

        2)确定终止条件

        如果是空节点 是不是二叉搜索树呢?

        是的,二叉搜索树也可以为空!

if (root == NULL) return true;

        3)确定单层递归的逻辑

bool left = isValid(root->left,pre);if (*pre != NULL && (*pre)->val >= root->val) return false;
*pre = root; // 记录前一个节点bool right = isValid(root->right,pre);
return left && right;

2.代码详解

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*/
bool isValid(struct TreeNode* root,struct TreeNode** pre) {if (root == NULL) return true;bool left = isValid(root->left,pre);if (*pre != NULL && (*pre)->val >= root->val) return false;*pre = root; // 记录前一个节点bool right = isValid(root->right,pre);return left && right;
}
bool isValidBST(struct TreeNode* root){struct TreeNode* pre = NULL;return isValid(root,&pre);
}

         如果你有问题或者有其他想法,欢迎评论区留言,大家可以一起探讨。

 

 

 

 

 

 

 

 

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

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

相关文章

Django框架之原始web框架优化

一、web应用框架简介及手撸web框架 软件开发架构详细&#xff1a;网络编程之网络架构及其趋势 - Xiao0101 - 博客园 (cnblogs.com) 软件开发架构分为两种&#xff1a; c/s架构&#xff1a;客户端软件(client)—服务端软件(server)b/s架构 &#xff1a;浏览器(Browser)------…

电子负载仪的远端控制

前言 最近研究了电子负载仪的远端控制&#xff08;区别于前面板控制&#xff09;&#xff0c;主要是用于程序控制&#xff0c;避免繁琐复杂的人工控制&#xff0c;举了南京嘉拓和艾维泰科的例子。 有纰漏请指出&#xff0c;转载请说明。 学习交流请发邮件 1280253714qq.com …

今日arXiv最热大模型论文:大模型也来看球,还能判断是否犯规

在足球世界&#xff0c;裁判的哨声可谓“千金难买”&#xff0c;因为它能直接决定俱乐部的钱包是鼓是瘪。但球场变化莫测&#xff0c;非常考验裁判的水平。 2022年卡塔尔世界杯上&#xff0c;半自动越位识别技术&#xff08;SAOT&#xff09;闪亮登场&#xff0c;通过12台摄像…

玩转nginx的配置文件3

1. limit_req_zone配置限流 limit_req_zone $binary_remote_addr zonemylimit:10m rate10r/s;upstream myweb {server 10.0.105.196:80 weight1 max_fails1 fail_timeout1;}server {listen 80;server_name localhost;location /login {limit_req zonemylimit;proxy_pass http:…

总结反思 持续进步-开源即时通讯(IM)项目OpenIM 新版本release-v3.7发布

背景 过去&#xff0c;我们团队对开源项目的认知较浅&#xff0c;过分追求进度&#xff0c;而忽视了代码的质量和规范。这导致了一些问题&#xff0c;例如部署流程设计不当&#xff1a;流程复杂、不规范&#xff0c;以及Mac与Windows部署的明显缺陷。这些问题不仅给开发者带来了…

Android Studio初学者实例:RecyclerView学习--模仿今日头条

本案例来自于学校的一个简单的课程实验 先看效果图&#xff0c;可以显然的看到&#xff0c;一些item是不同的布局&#xff0c;而其他布局就是简单的布局嵌套 看一下xml代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout …

抽象的代理模式1.0版本

前言&#xff1a; 在阅读Spring Security官方文档时&#xff0c;里面设计到了一种设计模式——代理模式Proxy 众里寻她千百度&#xff0c;蓦然回首&#xff0c;那人却在灯火阑珊处 开始 在之前的文章里陈述了一个观点——编程语言和语言没有区别 现看看我们日常生活中的代理…

[笔试训练](七)

目录 019&#xff1a;字符串中找出连续最长的数字串 020&#xff1a;岛屿数量 021&#xff1a;拼三角 019&#xff1a;字符串中找出连续最长的数字串 字符串中找出连续最长的数字串_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 边遍历边记下遇到的…

ionic 中对Input输入框、searchbar进行solr检索

一、概述 Ionic 是一个用于开发跨平台应用程序的开源工具&#xff0c;可以使用 Angular、React 或 Vue 等前端框架。要在 Ionic 应用程序中实现实时与 Solr 通信&#xff0c;可以使用 HTTP 客户端&#xff08;如 Angular 的 HttpClient 或 Ionic 的 Native HTTP&#xff09;…

鸿蒙入门11-DataPanel组件

数据面板组件 用于将多个数据的占比情况使用 占比图 进行展示 参数 参数形式 &#xff1a; DataPanel( options:{ values: number[], max?: number, type?: DataPanelType } ) 参数名 参数类型 是否必填 默认值 参数描述 values number[] 是 - 数据值列表 最大支持…

Feign功能详解、使用步骤、代码案例

简介&#xff1a;Feign是Netflix开发的声明式&#xff0c;模板化的HTTP客户端&#xff0c;简化了HTTP的远程服务的开发。Feign是在RestTemplate和Ribbon的基础上进一步封装&#xff0c;使用RestTemplate实现Http调用&#xff0c;使用Ribbon实现负载均衡。我们可以看成 Feign R…

IDEA快速入门

目录 1. 概述 2. 安装 3. 激活 4. 关闭自动更新 5. 创建Java项目 5.1 配置JRE 5.2 创建项目 6. 配置设置 6.1 主题 6.2 设置字体默认大小 6.3 鼠标滚轮改变字体大小 6.4 设置自动导入 6.5 项目选择 7. lombok插件 7.1 安装插件 7.2 启用注解 8. 安装包及插件…

linux-进程(2)

1.通过系统调用获取进程标示符 进程id&#xff08;PID&#xff09; 父进程id&#xff08;PPID&#xff09; 每一个可执行程序运行起来之后都会成为一个进程&#xff0c;每个进程都有一个自己的id&#xff0c;以及一个父进程id&#xff0c;父进程就是创建自己进程的进程&#xf…

一条龙-T检验+绘制boxplot

1.输入文件&#xff1a; 2.代码 #title:boxplot-5utr-cds-3tr-ATCG的百分比分布和T检验_封装函数版 rm(listls(allTRUE)) setwd("E:/R/Rscripts/5UTR_ABD_TE") library(tidyverse) library(ggplot2) # library(RColorBrewer) library(patchwork) library(dplyr) l…

Python-100-Days: Day01

Day01 Python简介 1.1989年Guido von Rossum在圣诞节之夜开始着手python语言编译器的编写。 2.1991年2月 Python v1 编译器诞生&#xff0c;使用C实现的&#xff0c;此时可以调用C的库函数。 3.1994年1月&#xff0c;Python v1.0 正式版发布。 4.2000年10月16日&#xff0…

新药品注册分类5大类的注册标准

在医药行业的浩瀚海洋中&#xff0c;药品注册分类就如同一座明亮的航标灯&#xff0c;指引着每一款新药从实验室走向市场&#xff0c;从理论概念变成患者手中的生命希望。本文将深入探讨化学药、中药、生物药的药品注册分类标准&#xff0c;药品分类常见问题、以及如何高效查询…

linux系统-深入学习文件系统与日志分析

目录 一、inode于block inode于block概括inode的内容inode包含文件的元信息用stat命令可以查看某个文件的inode信息Linux系统文件三个主要的时间属性目录文件架构 用户通过文件名打开文件时&#xff0c;系统内部的过程查看inode号码的实操硬盘分区后的结构 &#x1f447;用户访…

走向大规模应用之前,DePIN 如何突破技术、数据与市场之网

近期&#xff0c;随着分布式物理基础设施网络&#xff08;DePIN&#xff09;的快速演变&#xff0c;一个旨在利用区块链技术彻底改造传统基础设施模型的新兴生态系统正在逐渐浮现。2024 年 4 月&#xff0c;以 peaq 为代表的 DePIN 项目成功筹集了 1500 万美元用于生态系统的扩…

mac配置maven

在 macOS 上配置 Maven 也相对简单。以下是一种常用的方法&#xff1a; 1. 安装maven **下载 Maven&#xff1a;**首先&#xff0c;你需要从 Maven 官网&#xff08;https://maven.apache.org/download.cgi&#xff09;下载最新版本的 Maven。你可以选择二进制压缩包&#xf…

02.Scala简单演示

Scala创建对象的方法与Java有所不同 class可以直接传入形参&#xff1b; 形式为 变量名称&#xff1a;变量类型 逗号隔开 ** ** 方法定义也比较特殊 ** ** def方法名&#xff08;&#xff09;:返回值 { } 其中返回值Unit 等价于Java中的void