一、题目
题目链接:力扣
输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过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 。
限制:
0 <= 树的结点个数 <= 10000
二、题解
1、思路
🦄 自顶向下
- 对于当前遍历到的节点,计算左右子树的高度,如果左右子树的高度差是否不超过 1;
- 再分别递归地遍历左右子节点,并判断左子树和右子树是否平衡。
这是一个自顶向下的递归的过程。
🦄 自底向上
方法一由于是自顶向下递归,因此对于同一个节点,函数 height 会被重复调用,导致时间复杂度较高。如果使用自底向上的做法,则对于每个节点,函数 height 只会被调用一次。
自底向上递归的做法类似于后序遍历,对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡。如果一棵子树是平衡的,则返回其高度(高度一定是非负整数),否则返回 −1。如果存在一棵子树不平衡,则整个二叉树一定不平衡。
2、代码实现
🦄 自顶向下
class Solution {
public:
bool isBalanced(TreeNode* root) {
if(root == NULL)return true;
// bool cur_status = abs(depth(root->left) - depth (root->right)) < 2;// 当前结点是否满足左右子树深度差值不超过1
// bool l_status = isBalanced(root->left);// 左子树是否是平衡二叉树
// bool r_status = isBalanced(root->right);// 右子树是否是平衡二叉树
// return cur_status && l_status && r_status;
// 短路运算时间复杂度低些
return (abs(depth(root->left) - depth(root->right)) < 2) && isBalanced(root->left) && isBalanced(root->right);
}
private:
// 计算二叉树的深度
int depth(TreeNode* node)
{
if(node == NULL)return 0;
return 1 + max(depth(node->left), depth(node->right));
}
};
🦄 自底向上
class Solution {
public:
bool isBalanced(TreeNode* root) {
return height(root) != -1;// 返回树的深度或者-1
}
private:
// 直接在树的深度求解函数中判断当前节点是否满足左右子数长度相差不超过1
// 满足则返回当前树的长度,不满足则返回-1
int height(TreeNode* root)
{
if(root == NULL)return 0;
int left = height(root->left);
int right = height(root->right);
if(left == -1 || right == -1 || abs(left - right) > 1)
return -1;
else
return max(left, right) + 1;
}
};
3、复杂度分析
🦄 自顶向下
时间复杂度:O(n^2);平方
空间复杂度:O(n)。
🦄 自底向上
时间复杂度:O(n);
空间复杂度:O(n)。
4、运行结果
🦄 自顶向下
🦄 自底向上