题目:
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过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 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/balanced-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法一:朴素递归(自顶向下递归)
解题思路:
选中树中的任意一个结点,如何计算它的左、右子树的高度差?
答案是递归,从这个节点下探到叶子结点(root=null时返回,height=0),在返回途中height+1,最后递归完成,得到此结点的高度,这轮递归的时间复杂度是O(n);
上一步计算仅能确定一个结点的左右子树高度差,如果一棵树要满足平衡二叉树的条件,则需要任意一个结点都满足高度差不大于1,因此引出第二层递归:从根节点向下逐个结点判断(自顶向下)。这层递归的时间复杂度也是O(n),因此算法的整个时间复杂度是O(n^2)。
简言之,计算过程是 先分别计算树中每一个结点的高度差,再判断是否所有结点的高度差都不大于1。
关键点:
如何计算树中某个结点的高度:
左右子结点中的最大高度+1,即:max(leftChild, rightChild) + 1; 此即最小重复单元。
时间复杂度: O(n^2) //两轮递归
空间复杂度: O(n) //n是结点个数,递归调用的空间复杂度主要取决于递归调用的层数,递归调用的层数不会超过n
代码实例:
/**
* 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:
bool isBalanced(TreeNode* root) {
if(root == nullptr) return true;
bool curRes = abs(height(root->left) - height(root->right)) <= 1 ? true : false; //当前结点是否满足高度差<=1
bool leftRes = isBalanced(root->left);
bool rightRes = isBalanced(root->right);
return (curRes && leftRes && rightRes);
}
int height(TreeNode* root) {
if(root == nullptr) return 0;
int leftHeight = height(root->left);
int rightHeight = height(root->right);
return max(leftHeight, rightHeight) + 1;
}
};
解法二:优化递归(自底向上递归)
解题思路:
朴素递归的缺点是在计算出一个结点的左右子树高度差后,当计算此结点的父结点时要重新计算一遍这个节点的子树高度差。
优化的思路是在计算某个结点的高度差的递归返回过程中判断此结点是否已经不符合“左右子树高度差不大于1”这一条件,如不满足即可直接返回false,如满足则继续向上返回本结点的高度差结果(自底向上)。因此只需对树遍历一遍,整个算法的时间复杂度是O(n)。
时间复杂度: O(n)
空间复杂度: O(n)
代码实例:
/**
* 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:
bool isBalanced(TreeNode* root) {
return height(root) != -1;
}
int height(TreeNode* root) {
if(root == nullptr) return 0;
int leftHeight = height(root->left);
int rightHeight = height(root->right);
if(abs(rightHeight - leftHeight) > 1 || leftHeight == -1 || rightHeight == -1)
return -1;
return max(leftHeight, rightHeight) + 1;
}
};