1. 程式人生 > 實用技巧 >110. 平衡二叉樹(C++)

110. 平衡二叉樹(C++)

目錄

題目

給定一個二叉樹,判斷它是否是高度平衡的二叉樹。

本題中,一棵高度平衡二叉樹定義為:

一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過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 。

分析與題解

自頂向下遞迴

定義函式height,用於計算二叉樹中的任意一個節點 p的高度:

\[\text { height }(p)=\left\{\begin{array}{l} 0 \\ \max (\text { height }(p . l e f t), \text { height }(p . r i g h t))+1 \end{array}\right.\]

有了計算節點高度的函式,即可判斷二叉樹是否平衡。具體做法類似於二叉樹的前序遍歷,即對於當前遍歷到的節點,首先計算左右子樹的高度,如果左右子樹的高度差是否不超過 1,再分別遞迴地遍歷左右子節點,並判斷左子樹和右子樹是否平衡。這是一個自頂向下的遞迴的過程。

程式碼如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int getDepth(TreeNode* root){
        if(root==nullptr)
            return 0;
        return max(getDepth(root->left),getDepth(root->right))+1;
    }
    bool isBalanced(TreeNode* root) {
        if(root==nullptr)
            return true;
        int num = abs(getDepth(root->left) - getDepth(root->right));
        if(num<=1)
            return (isBalanced(root->left) && isBalanced(root->right));
        else
            return false;
    }
};

由於是自頂向下遞迴,因此對於同一個節點,函式getDepth()會被重複呼叫,演算法複雜度為O(n2),時間複雜度較高。

自底向上遞迴

如果使用自底向上的做法,則對於每個節點,函式只會被呼叫一次。

求height的程式碼與求深度的程式碼類似,只不過再遞迴求根結點前會進行判斷:

  • 左子樹結點已經不平衡
  • 右子樹結點已經不平衡
  • 左右height差值大於1

滿足上三條件任意一種便將根結點也返回-1。根結點最後的返回值其實是自底向上遍歷判斷所有結點的結果。程式碼如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int calHeight(TreeNode* root){
        if(root==nullptr)
            return 0;
        int leftHeight = calHeight(root->left);
        int rightHeight = calHeight(root->right);
        //相比於自頂向下遞迴,採用自底向上計算高度
        //在計算根結點高度過程中
        //已經對於左右子結點逐層進行平衡樹判斷
        if(leftHeight==-1 || rightHeight==-1 || abs(leftHeight-rightHeight)>1)
            return -1;
        else
            return max(leftHeight,rightHeight)+1;
        
    }

    bool isBalanced(TreeNode* root) {
        return calHeight(root)!=-1;
    }
};