平衡二叉樹的判斷
如何判斷是否為平衡二叉樹?
答:每個節點的左右子樹高度差的絕對值小於等於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) {}
* };
*/
自頂向下
偽碼描述
int getHeight(TreeNode* root){
if(root為空節點) return 0;
return 左子樹與右子樹的最大高度+1;
}
bool isBalanced(TreeNode* root){
if(root為空節點) return ture;
if(左子樹為平衡樹且右子樹為平衡樹)
if(左子樹與右子樹的高度差小於2)
return true;
return false;
}
Talk is cheap . Show me the code
int getHeight(TreeNode* root){
if(root==NULL) return 0;
return max(getHeight(root->right),getHeight(root->left))+1;
}
bool isBalanced(TreeNode* root) {
if(root==NULL) return true;
if(isBalanced(root->left)&&isBalanced(root->right))
if(abs(getHeight(root->left)-getHeight(root->right))<2)
return true;
return false;
}
算法分析:
時間復雜度:
\[O(n\log n) \]
空間復雜度:
\[O(n) \]
這不是最優算法,出現了很多冗余計算,getHeight
函數顯然要被重復調用很多次。計算每一個節點的時候,都重復計算了子節點的高度,浪費計算機算力,重復計算已經計算過的結果顯然是不合適的。
解決的辦法也呼之欲出,將每次計算出的高度傳出來保存不就好了?
於是有了下面自底向上的方法。這樣可以充分利用每次計算的高度的結果,降低計算量。
自底向上
偽碼描述
int isBalancedHelper(TreeNode* root,int& height){
if(root為空節點){
height=0;
return true;
}
int left,right;
if(判斷右子樹是否是平衡數並把高度賦給right&&判斷左子樹是否是平衡數並把高度賦給left)
if(left與right的差的絕對值小於2){
height=left與right的最大值+1;
return true;
}
return false;
}
bool isBalanced(TreeNode* root) {
int height=0;
return isBalancedHelper(root,height);
}
Talk is cheap . Show me the code
int isBalancedHelper(TreeNode* root,int& height){
if(root==NULL){
height=0;
return true;
}
int left,right;
if(isBalancedHelper(root->right,right)&&isBalancedHelper(root->left,left){
if(abs(left-right)<2)){
height=max(left,right)+1;
return true;
}
}
return false;
}
bool isBalanced(TreeNode* root) {
int height=0;
return isBalancedHelper(root,height);
}
算法分析:
時間復雜度:
\[O(n) \]
空間復雜度:
\[O(n) \]
自底向上每次判斷都把高度傳了出去,並且每一次計算都充分利用子節點的高度數據,沒有進行重復計算,在不提升空間復雜度的情況下,降低了整個算法的時間復雜度。