二叉树OJ题

 带值的多层递归

        对二叉树的递归性质做一个更好的补充。

        提到二叉树的递归,我们首相想到的就是二叉树的深度优先遍历(根遍历)。对于求二叉树结点的个数,同样可以用递归来实现(带值的多层递归)。

1、二叉树的结点数
int TreeSize(BTNode* root)
{if (root == NULL)return 0;elsereturn 1 + TreeSize(root->_left) + TreeSize(root->_right);
}

同理可以补充:求叶子结点数、树的深度。 

        2、二叉树的叶子结点数
int TreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}else if(root->_left == NULL && root->_right == NULL){return 1;}else{return TreeLeafSize(root->_left) + TreeLeafSize(root->_right);}
}
3、二叉树深度
int TreeDepth(BTNode* root)
{if (root == NULL){return 0;}else{return 1 + (TreeDepth(root->_left) > TreeDepth(root->_left) ? TreeDepth(root->_left) : TreeDepth(root->_left));}
}

OJ题

  1. 对于OJ题的VS调试,我们通常造一颗伪树.
  2. 对于二叉树的OJ题解法又不懂的地方,可以通过代码一步步画递归图来理解,我在这里只画较为复杂的几个。
1、二叉树的前序遍历

144. 二叉树的前序遍历 - 力扣(LeetCode),递归算法,迭代在C++中。

int TreeSize(struct TreeNode* root) {if (root == NULL)return 0;elsereturn 1 + TreeSize(root->left) + TreeSize(root->right);
}//求Tree的大小,用与内存开辟void _PreOrder(struct TreeNode* root, int* arr, int* pi) {if (root == NULL)return;/*假设树:A/ \ B   C*///第一次:arr[0]=根节点的值 i=i+1//第二次:arr[1]=左孩子的值 i++//第三次:左孩子的左孩子=NULL i不变//第四次:左孩子的右孩子=NULL i不变//第五次:arr[2]=右孩子的值 i++arr[*pi] = root->val;(*pi)++;//这两句相当于对结点的访问_PreOrder(root->left, arr, pi);_PreOrder(root->right, arr, pi);
}//递归的话不能直接用 preorderTraversal来递归,这样会开辟很多空间
int* preorderTraversal(struct TreeNode* root, int* returnSize) {int sz = TreeSize(root);int* retArr = (int*)malloc(sizeof(int) * sz);int i = 0;_PreOrder(root, retArr, &i);//i传地址才会改变否则返回时i的值不会改变*returnSize = sz;return retArr;
}

类似的: 

2、二叉树的中序遍历

94. 二叉树的中序遍历 - 力扣(LeetCode)

3、二叉树的后序遍历

145. 二叉树的后序遍历 - 力扣(LeetCode)

4、单值二叉树

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。

只有给定的树是单值二叉树时,才返回 true;否则返回 false

965. 单值二叉树 - 力扣(LeetCode)(把一颗二叉树看作 当前树、左子树、右子树

bool isUnivalTree(struct TreeNode* root) {if (root == NULL)return true; //树空即单值if (root->left != NULL && root->val != root->left->val)return false;//当前树与左不等if (root->right != NULL && root->val != root->right->val)return false;//当前树与右不等return isUnivalTree(root->left) && isUnivalTree(root->right);//判断左子树和右子树
}

5、最大深度 

104. 二叉树的最大深度 - 力扣(LeetCode)

相比于直接返回递归函数的计算,用两个变量存储,减少了重复的计算。

int maxDepth(struct TreeNode* root) {if(root==NULL)return 0;int leftDepth=maxDepth(root->left);int rightDepth=maxDepth(root->right);//return maxDepth(root->left)?maxDepth(root->right)...return leftDepth>rightDepth?leftDepth+1:rightDepth+1;
}
6、翻转二叉树

给定一棵二叉树的根节点 root,请左右翻转这棵二叉树,并返回其根节点

LCR 144. 翻转二叉树 - 力扣(LeetCode)(求二叉树的镜像)

//写法一:交换左右子树
struct TreeNode* flipTree(struct TreeNode* root) {if (root == NULL || (root->left == NULL && root->right == NULL))return root;struct TreeNode* tmp = root->left;root->left = root->right;root->right = tmp;flipTree(root->left);flipTree(root->right);return root;
}//解法二:利用返回值
struct TreeNode* flipTree(struct TreeNode* root) {if (root == NULL)return NULL;struct TreeNode* left = flipTree(root->left);struct TreeNode* right = flipTree(root->right);root->left = right;root->right = left;return root;
}
7、相同的树

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

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

100. 相同的树 - 力扣(LeetCode)

bool isSameTree(struct TreeNode* p, struct TreeNode* q) {if (p == NULL && q == NULL)return true;if (p == NULL && q != NULL)return false;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);
}
8、另一棵树的子树

        给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

        二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

572. 另一棵树的子树 - 力扣(LeetCode)

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);
}

 9、平衡二叉树

平衡二叉树:是指该树所有节点的左右子树的高度相差不超过 1。

给定一个二叉树,判断它是否是平衡二叉树。

110. 平衡二叉树 - 力扣(LeetCode):

bool isBalanced(struct TreeNode* root) {if (root == NULL)return true;int lefth = maxDepth(root->left);int righth = maxDepth(root->right);int gap = abs(lefth - righth);if (gap <= 1) {return isBalanced(root->left) && isBalanced(root->right);} else {return false;}
}
//对于N个节点的二叉树:只要遍历所有的结点,时间复杂度就是O(N)
//这个算法
//最好的时间复杂度是:O(N)
//最坏的时间复杂度是:O(N^2)

  可以把判断平衡二叉树的算法优化到O(N)吗?

1、时间复杂度大的原因:

  • 用的是前序判断,每次调用都会重复计算高度。
  • 存在大量的重复计算

2、优化

  • 用后序判断。
  • 在判断的同时计算数的高度。

(这里的优化是:后序求高度,减少了重复计算。较为复杂需要画图补充...)。

//后序判断优化
bool _isBalanced(struct TreeNode* root, int* pDepth) {if (root == NULL) {*pDepth = 0;return true;} else {int leftDepth = 0;if (_isBalanced(root->left, &leftDepth) == false)return false;int rightDepth = 0;if (_isBalanced(root->right, &rightDepth) == false)return false;if (abs(leftDepth - rightDepth) > 1)return false;*pDepth = leftDepth > rightDepth ? leftDepth+1 : rightDepth+1;return true;}
}bool isBalanced(struct TreeNode* root) {int depth = 0;return _isBalanced(root, &depth);
}
10、构建二叉树

即:还原二叉树,给定一个先序遍历的字符串序列,要求还原二叉树,并中序遍历该二叉树。

这道题的重点在于还原二叉树(二叉树的构建是递归的)。

对于一个先序序列能否还原二叉树:(#代表空格)

  • 完整的先序序列:abc##de#g##f###,可以还原整个二叉树。
  • 不完整的先序序列:abcdegf,无法还原二叉树,需要和中序序列联合还原。
typedef struct TreeNode {char val;struct TreeNode* left;struct TreeNode* right;
} TreeNode;TreeNode* CreateTree(char* str, int* pi) {if (str[*pi] == '#') {(*pi)++;return NULL;} else {TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));if (root == NULL) {printf("%s\n", strerror(errno));exit(-1);}root->val = str[*pi];(*pi)++;root->left = CreateTree(str, pi);//左子树递归构建root->right = CreateTree(str, pi);//右子树递归构建return root;}
}
//中序遍历
void Inorder(TreeNode* root) {if (root == NULL)return;Inorder(root->left);printf("%c", root->val);Inorder(root->right);
}int main() {char str[100];scanf("%s", str);int i = 0;TreeNode* root = CreateTree(str, &i);Inorder(root);
}

二叉树的核心思想就是:(当前树解决不了的问题交给左右子树)

分治算法:把大问题分解为小问题,小问题在进一步分解,直到不可再分解的子问题。

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

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

相关文章

算法刷题Day11: BM33 二叉树的镜像

点击题目链接 思路 转换为子问题&#xff1a;左右子树相反转。遍历手法&#xff1a;后序遍历 代码 class Solution:def Transverse(self,root: TreeNode):if root None:return rootnewleft self.Transverse(root.left)newright self.Transverse(root.right)# 对root节点…

leetcode104.二叉树的最大深度

给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;root [1,null,2] 输出…

一体式远程IO(三格电子)

一、功能概述 1.1 设备结构 本产品是三格电子研发生产的一体式远程 IO 。通信有 Profinet 、EtherCAT、 EtherNet/IP 三种。IO 接口有&#xff1a;32 路数字量输入、32 路数字量输出 NPN、32 路数字量输出 PNP、16 路数字量输入 16 路数字量输出 NPN、16 路数字量输入 16 路数…

零碳新墅居 | 重新定义零碳美学,阳光新能源打开高端品智生活新可能

当下人们对于居住生活的期待&#xff0c;不再仅限于实用与舒适&#xff0c;更追求绿色、低碳、美观与智能的结合。在这一趋势下&#xff0c;零碳墅居生活正成为引领高端生活风尚的新范式。 11月初&#xff0c;PChouse太平洋家居网携手阳光家庭能源官宣成立的“零碳新墅居设计智…

库存看板在现代企业管理中的作用:如何通过看板系统提升库存流动性与效率?

库存管理是现代企业管理中的重要环节&#xff0c;尤其对于制造业、零售业及电商平台等行业&#xff0c;如何高效、精准地管理库存&#xff0c;避免过度库存积压或库存不足的情况&#xff0c;直接影响到公司的运营成本、资金周转、客户满意度等多个方面。而在众多库存管理方法中…

免押租赁系统助力资源共享新模式开创便捷租赁体验

内容概要 免押租赁系统&#xff0c;听起来是不是很酷&#xff1f;这个新模式不仅仅是为了让你少花点钱&#xff0c;它的到来简直就是个革命&#xff01;以前&#xff0c;租东西时首先想到的就是那个令人心痛的押金&#xff0c;对吧&#xff1f;但现在&#xff0c;免押租赁系统…

Spring Boot 3 + Vue 3实战:实现用户登录功能

文章目录 一、实战概述二、实战步骤? &#xff08;一&#xff09;创建前端项目 - login-vue 1、创建Vue项目2、安装axios模块3、安装vue-router模块4、安装less和less-loader模块5、运行Vue项目6、在浏览器里访问首页7、在IDEA里打开Vue项目8、创建登录Vue组件9、创建首页Vue…

记录一次老平台改造通知用户刷新页面,纯前端实现

记录一次老平台改造通知用户刷新页面&#xff0c;纯前端实现 方案概述背景现状问题本质 方案设计前提设计实现 其他补充写在最后的话抛出一个问题 方案概述 背景 前端构建完上线&#xff0c;用户还停留还在老页面&#xff0c;用户不知道网页重新部署了&#xff0c;跳转页面的时…

11.12[CQU JAVEE_EXP3][JAVA WEB]3h速成JAVA WEB;DE启动Tomcat的各种BUG;GIT

GIT 如果有四个实验&#xff0c;但希望将四个实验保存在一个远程仓库当中&#xff0c;且分别有一个文件夹来区分&#xff0c;但是在本地写实验的时候&#xff0c;希望每次只打开一个实验&#xff0c;并且做完后向远程仓库中提交&#xff0c;不会拉取远程仓库中的其它实验代码 …

PYTHON编写API

API——application programming interface 全称为应用程序开发接口&#xff0c;是不同软件系统之间相互通信的桥梁。通过API&#xff0c;开发者可以通过标准化的请求和响应机制&#xff0c;访问服务器上的数据和功能&#xff0c;而无需了解具体的内部实现细节。在python中&am…

网络基础和UDP函数的简单使用

网络发展 最开始&#xff0c;计算机是独立的个体&#xff0c;因为需求需要计算机之间交换数据&#xff0c;由局域网&#xff08;私网&#xff09;–>广域网&#xff08;公网&#xff09;&#xff0c;网络就逐渐发展起来了。 初识协议 协议就是一种约定 网络协议就是众多协…

Netty入门教程——认识Netty

Netty入门教程——认识Netty 什么是Netty&#xff1f; Netty 是一个利用 Java 的高级网络的能力&#xff0c;隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。 Netty 是一个广泛使用的 Java 网络编程框架&#xff08;Netty 在 2011 年获得了Duke’s Choice …

调用大模型api 批量处理图像 保存到excel

最近需要调用大模型&#xff0c;并将结果保存到excel中&#xff0c;效果如下&#xff1a; 代码&#xff1a; import base64 from zhipuai import ZhipuAI import os import pandas as pd from openpyxl import Workbook from openpyxl.drawing.image import Image from io i…

Python基于TensorFlow实现BP和LSTM神经网络的空气质量预测并使用SHAP解释模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后关注获取。 1.项目背景 随着工业化进程的加速和城市化的扩展&#xff0c;空气污染成为全球面临的主要环境问题之一。空气质…

高效查找秘密武器一:位图

有这样的一个问题&#xff1a; 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数 中。 那么我们一般会想到这样做的 1.遍历&#xff0c;时间复杂度O(n) 2.排序&#xff08;N*logN&#xff09;&#xff0c…

对于小型企业,独立站和电商平台哪个更经济?

对于小型企业来说&#xff0c;选择独立站还是电商平台&#xff0c;需要根据各自的成本优势来决定。以下是一些关键点的比较&#xff1a; 平台费用&#xff1a; 电商平台&#xff1a;通常需要缴纳一定比例的交易佣金或年费&#xff0c;例如天猫、京东等平台的保证金和佣金费用相…

带权并查集和扩展域并查集的一些整理和理解(上)

请读者在有一定并查集基础上再阅读&#xff08;至少要知道什么是带权和扩展域并查集&#xff09; 在最近做题时候&#xff0c;我遇到了一些带权并查集和扩展域并查集的题目。我觉得它们都很难写也很难想&#xff0c;尤其是带权并查集我几乎第一时间无法想到是怎么做的&#xf…

json+Tomact项目报错怎么办?

在响应请求的时候&#xff0c;如果http响应没有指定响应数据的content-type&#xff0c;浏览器就不知道按照什么格式解析响应体的数据&#xff0c;因为浏览器只知道怎样解析http的行和头&#xff0c;再从头里获取响应体的字节长度和类型&#xff0c;按照你给的长度去截流&#…

极限激光雷达点云数据集

https://arxiv.org/pdf/2307.07607v5 ‎ - AirLab 他们的数据集里面有这么多极限场景 点云数据转换 他们的激光用的velodyne,录制的格式是【velodyne_msgs/VelodyneScan】 需要把【velodyne_msgs/VelodyneScan】转化成【sensor_msgs/PointCloud2】 我编译https://github.co…

信奥常考点:二叉树的构建(已知中序和 前序或后序 的情况下)

一、题目引入 这是来自CCF-GESP C七级认证 2024年9月的题目。 我们在此不解题&#xff0c;只把树画出来。 CCF-GESP 编程能力认证 C 七级 2024年9月份详细解析-CSDN博客 二、解题过程 我们可以根据先序遍历得出根节点是A&#xff0c;然后我们得到了A的左子树[B D]&#xff08;橙…