題目
輸入一棵二叉樹的根節點,判斷該樹是不是平衡二叉樹。如果某二叉樹中任意節點的左右子樹的深度相差不超過1,那麼它就是一棵平衡二叉樹。
示例 1:
給定二叉樹 [3,9,20,null,null,15,7]
3
/ \
9 20
/ \
15 7
返回 true
。
示例 2:
給定二叉樹 [1,2,2,3,3,null,null,4,4]
1
/ \
2 2
/ \
3 3
/ \
4 4
返回 false
。
限制:
1 <= 樹的結點個數 <= 10000
解題思路
解法一:先序遍歷 + 深度(從頂至底)
先構造一個獲取當前子樹的深度的函數 depth(root) ,通過比較某子樹的左右子樹的深度差 abs(depth(root.left) - depth(root.right)) <= 1 是否成立,來判斷某子樹是否是二叉平衡樹。若所有子樹都平衡,則此樹平衡。
算法流程:
isBalanced(root) 函數: 判斷樹 root 是否平衡
- 1)特例處理: 若樹根節點 root 爲空,則直接返回 true;
- 2)返回值: 所有子樹都需要滿足平衡樹性質,因此以下三者使用 && 連接:
- 2.1)abs(depth(root.left) - depth(root.right)) <= 1 :判斷當前子樹是否是平衡樹;
- 2.2)isBalanced(root.left) :判斷當前子樹的左子樹是否是平衡樹;
- 2.3)isBalanced(root.right) :判斷當前子樹的右子樹是否是平衡樹;
depth(root) 函數: 計算樹 root 的深度
- 1)終止條件:當 root 爲空,說明已越過葉節點,因此返回深度爲 0 。
- 2)遞推步驟:
- 2.1)計算節點 root 的左子樹的深度 left = epth(root.left);
- 2.2)計算節點 root 的右子樹的深度 right = depth(root.right);
- 3)返回值:返回此節點的深度,即 max(left, right) + 1。
解法二:後序遍歷 + 剪枝 (從底至頂)
解法一容易想到,但會產生大量重複計算,時間複雜度較高。
對二叉樹做後序遍歷,從底至頂返回子樹深度,若判定某子樹不是平衡樹則 “剪枝” ,直接向上返回。
算法流程:
recur(root) 函數:
- 1)當 root 爲空:說明越過葉節點,因此返回高度 0 ;
- 2)當左(右)子樹深度爲 -1:代表此樹的左(右)子樹不是平衡樹,因此剪枝,直接返回 −1 ;
- 3)當節點 root 左 / 右子樹的深度差 ≤ 1,則返回當前子樹的深度,即節點 root 的左 / 右子樹的深度最大值 +1,即 max(left, right) + 1 ;否則,直接返回 -1,代表此子樹不是平衡樹 。
isBalanced(root) 函數:
返回值: 若 recur(root) != -1 ,則說明此樹平衡,返回 true; 否則返回 false。
代碼
解法一:先序遍歷 + 深度(從頂至底)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null){
return true;
}
return Math.abs(depth(root.left)-depth(root.right))<=1 && isBalanced(root.left) && isBalanced(root.right);
}
private int depth(TreeNode root){
if(root == null){
return 0;
}
int left = depth(root.left);
int right = depth(root.right);
return Math.max(left, right) + 1;
}
}
解法二:後序遍歷 + 剪枝 (從底至頂)
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
return recur(root) != -1;
}
private int recur(TreeNode root){
if(root == null){
return 0;
}
int left = recur(root.left);
if(left == -1){
return -1;
}
int right = recur(root.right);
if(right == -1){
return -1;
}
return Math.abs(left-right)<=1 ? Math.max(left, right) + 1 : -1;
}
}