剑指 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 条评论
登录 后参与评论

相关文章

来自专栏calmound

Set Matrix Zeroes

问题:将数组中的某个值为0的元素所在行和列的其他值都为0 分析;遍历数组找到某一值为0然后遍历他的上下左右直到边界,要用while而不能用搜索,因为搜索过去新节...

3315
来自专栏抠抠空间

python内置函数大全

 数学运算 abs:求数值的绝对值 >>> abs(-2) 2 divmod:返回两个数值的商和余数 >>> divmod(5,2) (2, 1) >> d...

2646
来自专栏来自地球男人的部落格

[LeetCode] 74. Search a 2D Matrix

【原题】 Write an efficient algorithm that searches for a value in an m x n matrix. ...

1828
来自专栏面朝大海春暖花开

set集合

HashSet:哈希表是通过使用称为散列法的机制来存储信息的,元素并没有以某种特定顺序来存放;

711
来自专栏小狼的世界

Python 3.6学习笔记(一)

可以看到,注释以#开头,python的变量不需要任何前缀,行结束不需要结束符号,非常符合我们自然语言的阅读和书写习惯。当语句以:结尾时,缩紧的语句视为代码块。

762
来自专栏Python爬虫与算法进阶

Leetcode-Solutions 1.two-sum (Python&Golang)

恩,最后找队友一起刷题。喜欢可以联系我 ,来公众号“Python爬虫与算法进阶”找我哦

3679
来自专栏赵俊的Java专栏

落单的数

1632
来自专栏Python

re模块和正则表达式

re模块 讲正题之前我们先来看一个例子:https://reg.jd.com/reg/person?ReturnUrl=https%3A//www.jd.com...

2445
来自专栏日常分享

Java 通过先序中序序列生成二叉树

  二叉树的前序以及后续序列,以空格间隔每个元素,重构二叉树,最后输出二叉树的三种遍历方式的序列以验证。

741
来自专栏数据结构与算法

2010 求后序遍历

2010 求后序遍历 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 白银 Silver 题目描述 Description 输入一...

3086

扫描关注云+社区