[LeetCode](面試題55 - II)平衡二叉樹

題目

輸入一棵二叉樹的根節點,判斷該樹是不是平衡二叉樹。如果某二叉樹中任意節點的左右子樹的深度相差不超過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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章