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

相关文章

来自专栏向治洪

ArrayList和LinkedList的区别

一般大家都知道ArrayList和LinkedList的大致区别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构...

1859
来自专栏书山有路勤为径

二叉查找树转换为较大树

Leetcode 538 已知一个二叉查找树,将它转换为一个较大树,即所有的二叉查找树的节点,赋值为该节点本身的值与该节点大的节点的值的和

802
来自专栏彭湖湾的编程世界

【算法】论平衡二叉树(AVL)的正确种植方法

参考资料 《算法(java)》                           — — Robert Sedgewick, Kevin Wayne 《数据结...

30311
来自专栏程序生活

二叉树的深度

题目描述 输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。 代码实现 递归实现 # ...

2494
来自专栏青玉伏案

算法与数据结构(十一) 平衡二叉树(AVL树)(Swift版)

今天的博客是在上一篇博客的基础上进行的延伸。上一篇博客我们主要聊了二叉排序树,详情请戳《二叉排序树的查找、插入与删除》。本篇博客我们就在二叉排序树的基础上来聊聊...

2267
来自专栏熊二哥

深入入门系列--Data Structure--04树

终于有机会重新回头学习一下一直困扰自身多年的数据结构了,赶脚棒棒哒。一直以来,对数据结构的掌握基本局限于线性表,稍微对树有一丢丢了解,而对于图那基本上就是不懂(...

1829
来自专栏曾大稳的博客

树(Tree)以及二叉树的遍历

树(tree) 是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限节点组成一个具有层次...

1271
来自专栏WindCoder

DateUtil-常用关于date的工具类备份

671
来自专栏彭湖湾的编程世界

【算法】论平衡二叉树(AVL)的正确种植方法

《算法(java)》                           — — Robert Sedgewick, Kevin Wayne

972
来自专栏编程理解

数据结构(六):红黑树

级别的查询、插入和删除节点复杂度。相对于 AVL 树单纯的对每个节点的平衡因子进行判断,红黑树给节点赋予了颜色属性,并通过对树中节点的颜色进行限制,来保持整棵...

1532

扫码关注云+社区