給定一個二叉樹,判斷它是否是高度平衡的二叉樹。
本題中,一棵高度平衡二叉樹定義爲:
一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過1。
通常認爲此問題有兩種解決方案:自上而下 / 自下而上的方法。
思路1:自上而下
第一種方法嚴格按照平衡二叉樹的定義檢查樹是否平衡:兩個子樹的高度之差不大於1,並且左子樹和右子樹也都平衡。使用輔助函數 calDepth(),我們可以輕鬆地編寫代碼:
代碼
class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
return (Math.abs(calDepth(root.left) - calDepth(root.right)) <= 1) && isBalanced(root.left) && isBalanced(root.right);
}
private int calDepth(TreeNode root) {
if (root == null) return 0;
return Math.max(calDepth(root.left), calDepth(root.right)) + 1;
}
}
對於當前節點根,實際上調用其左側和右側子節點的calDepth()實際上必須訪問其所有子節點,因此複雜度爲O(N)。我們對樹中的每個節點執行此操作,因此isBalanced的總體複雜度將爲 O(N ^ 2)。
思路2:自下而上
第二種方法基於DFS。而不是爲每個子節點顯式調用 calDepth(),而是在DFS遞歸中返回當前節點的高度。.
噹噹前節點(含)的子樹平衡時,函數dfsHeight()返回一個非負值作爲高度。否則返回-1。
根據兩個子節點的leftHeight和rightHeight,父節點可以檢查子樹是否平衡,並確定其返回值。
在這種自下而上的方法中,樹中的每個節點僅需要訪問一次,因爲每個節點的高度已經被記錄並返回給遞歸的上一層,上層節點求高度時直接用,而不是如方法1每個節點都得往下求一次高度。
因此,時間複雜度爲O(N),優於第一種解決方案。
代碼
class Solution {
public boolean isBalanced(TreeNode root) {
return dfsHeight (root) != -1;
}
private int dfsHeight (TreeNode root) {
if (root == null) return 0;
// 求左子樹高度
int leftHeight = dfsHeight (root.left);
if (leftHeight == -1) return -1;
// 求右子樹高度
int rightHeight = dfsHeight (root.right);
if (rightHeight == -1) return -1;
// 判斷當前節點爲根的樹,是否不平衡
if (Math.abs(leftHeight - rightHeight) > 1) return -1;
// 返回當前樹的高度
return Math.max (leftHeight, rightHeight) + 1;
}
}