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;
}
};