110. 平衡二叉樹(C++)
阿新 • • 發佈:2020-09-02
目錄
題目
給定一個二叉樹,判斷它是否是高度平衡的二叉樹。
本題中,一棵高度平衡二叉樹定義為:
一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過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; } };