剑指 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;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏10km的专栏

cuda8+cuDNN Faster R-CNN安装塈运行demo

安装cuda cuda8安装参见网上教程 安装cuDNN py-faster-rcnn/caffe-fast-rcnn目前不支持cuDNN5。 如果使用cu...

2896
来自专栏张善友的专栏

Firebird 数据库资源

Firebird is a database with 20 years of history, full set of features (including...

2278
来自专栏张善友的专栏

How does it work in Mono's C# compiler?

Introduction Mono is an Open Source free programming language project. It is an ...

2777
来自专栏大内老A

MS Enterprise Library 5.0发布!!

What is Enterprise Library Enterprise Library is a collection of reusable softwa...

1725
来自专栏码匠的流水账

使用webflux提升数据导出效率

两种方法目前看来用时差不多,不过后者可以避免超时。当然使用传统mvc也可以实现类似效果,就是拿到response的输出流不断地write和flush。不过web...

1882
来自专栏用户2442861的专栏

win10 安装 Cygwin

http://preshing.com/20141108/how-to-install-the-latest-gcc-on-windows/

1643
来自专栏我和未来有约会

silverlight寻奇 - Graphite

Graphite是一个能自动布局的图表控件。 目前它已经有了silverlight 2 和 wpf的版本。观看demo时按下“Ctrl”键再做点击操作。 原文...

1795
来自专栏张善友的专栏

更新Silverlight ctp到Silverlight beta 1.0

下面是我更新Silverlight ctp到Silverlight beta 1.0的一个纪录,希望对各位同学有帮助。 1、卸载Silverlight ctp ...

1759
来自专栏fangyangcoder

基于FPGA的IIR滤波器

                                                        by方阳

1351
来自专栏walterlv - 吕毅的博客

Reading the Source Code of Microsoft.NET.Sdk, Writing the Creative Extension of Compiling

发布于 2018-06-30 12:27 更新于 2018-08...

612

扫码关注云+社区