1. 程式人生 > 其它 >劍指 offer程式碼解析——面試題39判斷平衡二叉樹(高效方法)

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