剑指 offer代码解析——面试题39判断平衡二叉树(高效方法)
时间:2022-05-03
本文章向大家介绍剑指 offer代码解析——面试题39判断平衡二叉树(高效方法),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目:输入一颗二叉树的根结点,判断该树是不是平衡二叉树。
如果某二叉树中任意结点的左右子树的高度相差不超过1,那么它就是一棵平衡二叉树。
分析:所谓平衡二叉树就是要确保每个结点的左子树与右子树的高度差在-1到1之间。
由于之前一题已经给出了二叉树高度的计算方法,因此本题最直观的思路就是分别计算每个结点的左子树高和右子树高,从而判断一棵树的所有结点是否均为平衡二叉树。
上一篇博客中采用了一种较为常规的思路,但由于涉及到重复计算子树的高度,因此性能并不好,接下来提出一种从下而上,依次判断每个子树是否为平衡二叉树的同时计算每棵子树的高度,并将其记录下供上层结点使用。
常规思路请移步至:点击打开链接
上述方法效率很低,因为采用了从上至下的判断方向,因此某些结点的高度被重复计算。
若要避免高度的重复计算,我们需要从下至上计算每棵子树的高度,并保存每棵子树的高度,供上方的结点在计算高度时使用。
若要从下至上遍历结点,那就得使用后序遍历,先遍历左右子树,最后遍历根结点。
/**
* 题目:输入一颗二叉树的根结点,判断该树是不是平衡二叉树。
* 如果某二叉树中任意结点的左右子树的高度相差不超过1,那么它就是一棵平衡二叉树。
* @author 大闲人柴毛毛
* @date 2016年4月2日
*/
public class BalanceTree {
/**
* 上述方法效率很低,因为采用了从上至下的判断方向,因此某些结点的高度被重复计算。
* 若要避免高度的重复计算,我们需要从下至上计算每棵子树的高度,并保存每棵子树的高度,供上方的结点在计算高度时使用。
* 若要从下至上遍历结点,那就得使用后序遍历,先遍历左右子树,最后遍历根结点。
* 代码如下:
*/
Height height = new Height();
public static <T> boolean isBalanceTree_2(Node<T> root,Height height){
//健壮性判断:若树为空
if(root==null){
height.height = 0;
return true;
}
Height left_height = new Height();
Height right_height = new Height();
//若左右子树均是平衡二叉树
if(isBalanceTree_2(root.left,left_height) && isBalanceTree_2(root.right,right_height)){
//判断当前是否为平衡二叉树
int diff = left_height.height-right_height.height;
if(diff==-1 || diff==1 || diff==0){
//计算当前子树的高度
height.height = (left_height.height<right_height.height ? right_height.height : left_height.height)+1;
return true;
}
return false;
}
return false;
}
/**
* 测试
*/
public static void main(String[] args){
//构造一棵平衡二叉树
Node<Integer> node1 = new Node<Integer>();
Node<Integer> node2 = new Node<Integer>();
Node<Integer> node3 = new Node<Integer>();
Node<Integer> node4 = new Node<Integer>();
Node<Integer> node5 = new Node<Integer>();
Node<Integer> node6 = new Node<Integer>();
Node<Integer> node7 = new Node<Integer>();
Node<Integer> node8 = new Node<Integer>();
Node<Integer> node9 = new Node<Integer>();
node1.data = 1;
node2.data = 2;
node3.data = 3;
node4.data = 4;
node5.data = 5;
node6.data = 6;
node7.data = 7;
node8.data = 8;
node9.data = 9;
node1.left = node2;
node1.right = node3;
node2.left = node4;
node2.right = node5;
node5.left = node7;
node3.right = node6;
// node7.left = node8;
// node8.left = node9;
System.out.println(isBalanceTree_2(node1,new Height()));
}
}
//存放当前树的高度
class Height{
int height;
}
- 网站每日PV/IP统计/总带宽/URL统计脚本分享(依据网站访问日志)
- 查看服务器系统资源(cpu,内容)利用率前几位的进程的方法
- 腾讯云平台部总经理陈磊:大数据背后的技术支撑
- DataSet与Xml相互转化
- SqlTransaction事务使用示例
- nginx的web缓存服务环境部署记录
- nginx反向代理+缓存开启+url重写+负载均衡(带健康探测)的部署记录
- [转自blueidea]像table一样布局div Ⅰ
- 如何对动态创建控件进行验证以及在Ajax环境中的使用
- 升级个人网站框架组件IBatisNet+Castle
- 如何在多线程中调用winform窗体控件
- gerrit代码简单备份方案分享
- svn代码发版的脚本分享
- 正则表达式提取指定内容
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- mysql事务隔离级别详解和实战
- ELK+FileBeat+Kafka分布式系统搭建图文教程
- Flink CEP 原理和案例详解
- 实战开发,使用 Spring Session 与 Spring security 完成网站登录改造!!
- 分布式计算框架Gearman原理详解
- 【从0开始の全记录】Flume+Kafka+Spark+Spring Boot 统计网页访问量项目
- 系统级性能分析工具perf的介绍与使用[转]
- 深入理解排序算法
- 用nginx缓存静态文件
- 优雅的玩PHP多进程
- 聊一聊mycat数据库集群系列之双主双重实现
- Fast-SCNN的解释以及使用Tensorflow 2.0的实现
- 基于Spring Boot快速实现发送邮件功能
- 史上最全的vim快捷键文档/手册/大全/帮助/指南
- RPC详解