LeetCode面试题04 检查平衡性

题目:

实现一个函数,检查二叉树是否平衡。在这个问题中,平衡树的定义如下:任意一个节点,其两棵子树的高度差不超过 1。

一、平衡树定义:

二叉树,一种由节点组成的树形数据结构,每个节点最多有两个子节点,分别称作左子节点和右子节点。而平衡二叉树,可不是普通的二叉树,它有着严苛的要求:对于树中的任意一个节点,其两棵子树(左子树和右子树)的高度差不能超过 1。这个定义看似简单,实则暗藏玄机,它关乎二叉树的查找效率、稳定性等诸多性能指标。想象一下,如果一棵二叉树极度不平衡,就如同瘸腿走路,某些操作的耗时会大幅增加,效率大打折扣。

举个例子,在一棵平衡二叉搜索树里,查找一个元素的时间复杂度接近O(\log n)。可要是树失衡了,最坏情况下查找时间复杂度能退化成O(n),这差距可就太悬殊了。

二、解题思路拆解

整体思路概述

拿到这道题,要判断一棵二叉树是否平衡,关键在于检查树中每个节点的左右子树高度差是否都不超过 1。所以整体思路是通过遍历二叉树的每个节点,去获取并比较其左右子树的高度,进而得出整棵树是否平衡的结论,通常会采用递归的方式来实现这个过程。

(一)计算子树高度

咱们得先打造一个 “高度测量仪”,也就是一个专门计算以某个节点为根节点的子树高度的函数。递归在这里大展拳脚,其逻辑简洁而巧妙:当节点为空时,好比遇到了树的 “尽头”,高度自然是 0;要是节点非空,那这棵子树的高度就得看它左右 “臂膀”(左右子树)谁更长了,取两者高度最大值,再给它加上 1(把当前节点这一层算上)。以下是用 C 语言展示的代码片段:

//计算树的高度的辅助函数
int treeHeight(struct TreeNode* node) {if (node == NULL) {return 0;}int leftHeight = treeHeight(node->left);int rightHeight = treeHeight(node->right);return (leftHeight > rightHeight? leftHeight : rightHeight) + 1;
}

在这段代码里,先是递归地深挖 node 的左子树高度存进 leftHeight,再探寻右子树高度存入 rightHeight,最后掐指一算,挑出大值加 1 返回,完美算出子树高度。 

(二)判断节点平衡性与整树遍历

有了测量子树高度的 “神器”,下一步就是打造主函数来宣判二叉树的 “平衡命运” 了。首先要照顾到特殊情况,要是根节点就是空的,那没得说,这棵树妥妥是平衡的,直接返回 true,皆大欢喜。

碰上根节点非空时,就得严肃起来了。先用刚才的函数量出根节点左右子树各自的高度,要是这俩高度差的绝对值大于 1,那这棵树在根节点这儿就 “崴脚” 了,立马返回 false,宣判它不平衡。

但事情还没完,即便当前根节点这关过了,它的子树里说不定还有 “定时炸弹” (不平衡的节点)呢。所以得接着递归调用主函数,分别去审查左子树和右子树是否平衡,只有左右子树都稳稳当当、符合平衡标准,这整棵树才算得上是平衡的,故而最终返回对左右子树递归判断结果的逻辑与(&&)。用代码说话:

bool isBalanced(struct TreeNode* root) {if (root == NULL) {return true;}int leftHeight = treeHeight(root->left);int rightHeight = treeHeight(root->right);if (abs(leftHeight - rightHeight) > 1) {return false;}return isBalanced(root->left) && isBalanced(root->right);
}

 三、代码实现

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>//定义树的结构体
struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;
};// 构建二叉树节点的函数(辅助函数,方便创建测试用的二叉树)
struct TreeNode* createNode(int val) {struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));newNode->val = val;newNode->left = NULL;newNode->right = NULL;return newNode;
}// 计算树的高度的辅助函数
int treeHeight(struct TreeNode* node) {if (node == NULL) {return 0;}// 递归计算左子树高度int leftHeight = treeHeight(node->left);// 递归计算右子树高度int rightHeight = treeHeight(node->right);// 取左右子树中较大的高度加1(根节点算一层)作为当前节点所在子树的高度return (leftHeight > rightHeight? leftHeight : rightHeight) + 1;
}bool isBalanced (struct TreeNode* root)
{if (root==NULL){return true;}// 计算左子树高度int leftHeight = treeHeight(root->left);// 计算右子树高度int rightHeight = treeHeight(root->right);// 判断当前节点的左右子树高度差是否超过1,若超过则不平衡if (abs(leftHeight - rightHeight) > 1) {return false;}// 递归地判断左子树和右子树是否平衡return isBalanced(root->left) && isBalanced(root->right);
};int main(){
//构建一个二叉树struct TreeNode* root = createNode(3);root->left = createNode(9);root->right = createNode(20);root->right->left=createNode(15);root->right->right=createNode(7);bool result = isBalanced(root);if (result) {printf("该二叉树是平衡二叉树\n");} else {printf("该二叉树不是平衡二叉树\n");}return 0;
}

四、代码实现细节与优化点

上面给出的代码是基于 C 语言结构体实现二叉树节点的经典范例。代码结构清晰,两个函数各司其职,一个专心算高度,一个全力判断平衡。

不过呢,这代码还有优化空间。现在计算子树高度和判断平衡的过程中存在重复计算,每次判断一个节点的平衡性,都要重新完整计算左右子树高度,当树规模大时,计算量冗余严重。优化思路是把高度计算与平衡判断合二为一,一边计算高度一边检查平衡性,一旦发现不平衡就及时止损,不再做无用功。这种改进能大幅削减不必要的计算,提升算法效率。

五、改进代码实现

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>// 定义二叉树节点结构体
struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;
};// 构建二叉树节点的函数(辅助函数,方便创建测试用的二叉树)
struct TreeNode* createNode(int val) {struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));newNode->val = val;newNode->left = NULL;newNode->right = NULL;return newNode;
}// 优化后的函数,同时计算高度并判断是否平衡,返回值大于等于0表示当前子树的高度,返回 -1表示子树不平衡
int isBalancedAndHeight(struct TreeNode* node) {if (node == NULL) {return 0;}// 递归计算左子树高度并判断平衡性int leftHeight = isBalancedAndHeight(node->left);if (leftHeight == -1) {return -1;}// 递归计算右子树高度并判断平衡性int rightHeight = isBalancedAndHeight(node->right);if (rightHeight == -1) {return -1;}// 检查当前节点的左右子树高度差是否超过1if (abs(leftHeight - rightHeight) > 1) {return -1;}// 返回当前子树高度(左右子树中较大高度 + 1)return (leftHeight > rightHeight? leftHeight : rightHeight) + 1;
}// 判断二叉树是否平衡的主函数,调用优化后的辅助函数进行判断
bool isBalanced(struct TreeNode* root) {return isBalancedAndHeight(root)!= -1;
}int main() {// 构建一个简单的二叉树示例(这里你可以自行修改节点值和结构来测试不同情况)struct TreeNode* root = createNode(3);root->left = createNode(9);root->right = createNode(20);root->right->left=createNode(15);root->right->right=createNode(7);bool result = isBalanced(root);if (result) {printf("该二叉树是平衡二叉树\n");} else {printf("该二叉树不是平衡二叉树\n");}return 0;
}

总结与拓展

判断二叉树是否平衡不仅是一道算法面试高频题,更是深入理解二叉树特性的绝佳契机。通过递归手段巧妙遍历、精准测量、严谨比对,我们能稳稳拿捏二叉树的平衡状况。往后再遇到二叉树相关复杂操作,像是构建平衡二叉搜索树、优化树的存储与查找等,这判断平衡的技巧都能派上大用场。

掌握了二叉树平衡判断,就像是拿到了二叉树世界的一把钥匙,诸多神秘大门将徐徐向你敞开。不管是继续刷题深造,还是实际项目里优化数据结构,都能底气十足、游刃有余。要是你对这篇博客内容有啥疑问、想法,或是独到见解,欢迎随时留言交流,咱们一起在算法海洋破浪前行!

 

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

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

相关文章

【一文了解】C#基础-接口

目录 1. 定义 2. 接口的特点与规则 3. 接口的实现 3.1单接口实现 3.2多接口实现 4. 接口的作用和用途 1)扩展行为 2)规范行为 3)降低耦合 5. 接口与继承的比较 1)继承 2)接口 6. 接口与抽象类的比较 1)IComparable(比较器&#xff0c;常用) 2)IComparer(比较器)…

Notable是一款优秀开源免费的Markdown编辑器

一、Notable简介 ‌ Notable‌是一款开源的跨平台Markdown编辑器&#xff0c;支持Linux、MacOS、Windows以及国产操作系统等多种主流操作系统。它以其高颜值和强大的功能&#xff0c;成为了许多用户的首选工具。 主要特性 实时预览‌&#xff1a; Notable提供了实时预览功能&…

方案解读:46页数字化企业制造运营管理(MOM)系统运营实践方案

本文概述了数字化企业制造运营管理(MOM)系统的核心要素与实践路径,深入探讨了数字化企业建设的丰富内涵。数字化企业以智能制造为核心,融合了智能终端、智能制造单元、工业4.0边缘技术、赛博物理系统(CPS)等前沿技术,构建了数字化车间、智能工厂等高效生产环境。通过工业…

安卓报错Switch Maven repository ‘maven‘....解决办法

例如&#xff1a;Switch Maven repository ‘maven(http://developer.huawei.com/repo/)’ to redirect to a secure protocol 在库链接上方添加配置代码&#xff1a;allowInsecureProtocol true

es实现上传文件查询

es实现上传文件查询 上传文件&#xff0c;获取文件内容base64&#xff0c;使用es的ingest-attachment文本抽取管道转换为文字存储 安装插件 通过命令行安装&#xff08;推荐&#xff09; 1.进入 Elasticsearch 安装目录 2.使用 elasticsearch-plugin 命令安装 bin/elastics…

采集opc ua转profinet IO项目案例

目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 准备工作 2 4 配置VFBOX网关采集OPC UA的数据 2 5 用PROFINET IO协议转发数据 4 6 案例总结 6 1 案例说明 设置网关采集OPC UA设备数据把采集的数据转成profinet IO协议转发给其他系统。 2 VFBOX网关工作原理 VFBOX网关是协议转换…

linux 安装composer

下载composer curl -sS https://getcomposer.org/installer | php下载后设置环境变量&#xff0c;直接通过命令composer -v mv composer.phar /usr/local/bin/composer查看版本看是否安装成功 composer -v

可视化建模以及UML期末复习----做题篇

一、单项选择题。&#xff08;20小题&#xff0c;每小题2分,共40分&#xff09; 1、UML图不包括&#xff08; &#xff09; A、用例图 B、状态机图 C、流程图 D、类图 E、通信图 答案&#xff1a;C、流程图 UML中不包括传统意义上的流程图&#xff0c;流程图通常是指B…

VBA高级应用30例应用在Excel中的ListObject对象:向表中添加注释

《VBA高级应用30例》&#xff08;版权10178985&#xff09;&#xff0c;是我推出的第十套教程&#xff0c;教程是专门针对高级学员在学习VBA过程中提高路途上的案例展开&#xff0c;这套教程案例与理论结合&#xff0c;紧贴“实战”&#xff0c;并做“战术总结”&#xff0c;以…

Mac mini m4本地跑大模型(ollama + llama + ComfyUI + Stable Diffusion | flux)

安装chat大模型&#xff08;不推荐&#xff0c;本地运行的大模型只能聊废话&#xff0c;不如网页版使用openAI等高效&#xff09; 首先下载ollama的安装包 https://ollama.com/ 点击启动访问&#xff1a;http://localhost:11434 Ollama is running 代表已经运行起来了&#x…

借助Aspose.Cells ,在 Excel 中将文本转换为数字

在 Excel 中将文本转换为数字是一项常见要求。许多用户会遇到以文本形式存储的数字&#xff0c;这可能会导致计算错误。此问题会影响财务、数据分析和报告。将这些文本条目转换为实际数字对于准确的数据处理至关重要。在这篇博文中&#xff0c;我们将探讨如何使用 C# 将以文本形…

mysql 报错 World-writable config file ‘/etc/my.cnf‘ is ignored.

/etc/my.cnf 配置文件, 或着docker 挂载的配置文件(宿主机中的配置文件),权限过大 如是二进制启动 chmod 644 /etc/my.cnf 如是docker启动 chmod 644 /opt/docker-data/mysql/conf/my.cnf 重启服务,就可以了 MySQL篇之解决启动时报错&#xff1a;Warning: World-writable …

Erlang socket编程(二)

模拟服务器和客户端通信 %%%------------------------------------------------------------------- %%% author Administrator %%% copyright (C) 2024, <COMPANY> %%% doc %%% %%% end %%% Created : 03. 12月 2024 22:28 %%%---------------------------------------…

2024 年 11 月区块链游戏研报:牛市加持下的 GameFi 破局之路

2024 年 11 月区块链游戏研报 作者&#xff1a;Stella L (stellafootprint.network) 数据来源&#xff1a;Footprint Analytics 区块链游戏 Research 页面 2024 年 11 月 Web3 游戏行业市场增长显著但大规模采用策略仍在演进。随着比特币创下历史新高并接近 10 万美元里程碑…

使用ssh免密登录实现自动化部署rsync+nfs+lsync(脚本)

单机一键部署sshrsyncnfslsync 执行准备 主机信息 主机角色外网IP内网IP主机名nfs、lsync10.0.0.31176.16.1.31nfs客户端10.0.0.7176.16.1.7web01rsync、nfs10.0.0.41172.16.1.41backup 秘钥信息 #web01可以免密连接nfs和backup [rootweb01 ~]# ssh-keygen [rootweb01 ~]#…

数据质量规则(Data Quality Rules)

数据质量规则&#xff08;Data Quality Rules&#xff09;是指用来确保数据的准确性、完整性、一致性和可用性的标准或逻辑规则。这些规则通常在数据集成、数据存储和数据分析过程中执行&#xff0c;以保证数据符合预期的业务需求或技术规范。 以下是数据质量规则的分类及其内…

QT 多级嵌套结构体,遍历成员--半自动。<模板+宏定义>QTreeWidget树结构显示

Qt的QTreeWidget来显示嵌套结构体的成员&#xff0c;并以树形结构展示。 #include <QApplication> #include <QTreeWidget> #include <QTreeWidgetItem> #include <QString> #include <cstdint>// 假设这些是你的结构体定义 struct BaseMeterPa…

用Go语言重写Linux系统命令 -- nc简化版

用Go语言重写Linux系统命令 – nc简化版 1. 引言 netcat&#xff0c;简称 nc&#xff0c;被誉为网络工具中的“瑞士军刀”&#xff0c;是网络调试与分析的利器。它的功能十分强大&#xff0c;然而平时我们经常使用的就是他的连通性测试功能&#xff0c;但是nc是被设计用来测试…

【JAVA高级篇教学】第一篇:Springboot对接通义千问大模型

博主今天打算讲解下Java如何对接阿里云的通义千问大模型&#xff0c;可以自己玩玩ai问答之类的&#xff01; 目录 一、发展历程 二、API-KEY的获取与配置 三、引用SDK 四、文本模型 1.代码 2.返回数据 3.官方代码案例 五、通义千问VL 1.计量计费 六、查看API-KEY调用额…

LeetCode 每日一题 2024/12/2-2024/12/8

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 12/2 52. N 皇后 II12/3 3274. 检查棋盘方格颜色是否相同12/4 2056. 棋盘上有效移动组合的数目12/5 3001. 捕获黑皇后需要的最少移动次数12/6 999. 可以被一步捕获的棋子数…