题目:
题目链接:力扣https://leetcode-cn.com/problems/balanced-binary-tree/
难度简单991
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:true示例 2:
输入:root = [1,2,2,3,3,null,null,4,4] 输出:false示例 3:
输入:root = [] 输出:true提示:
- 树中的节点数在范围
[0, 5000]
内-104 <= Node.val <= 104
核心:
需要掌握如何求出二叉树中某个节点的高度,理解其过程。
参考链接:计算二叉树的某个节点的高度_Morning sunshine的博客-CSDN博客
·
思路1:
从根节点开始,
先计算当前节点的左子节点与右子节点的高度,然后判断高度差是否>1
如果>1,则直接返回false;
如果<=1,则以左子结点和右子节点为新的父节点,继续递归判断;
·
代码示例:
/**
* 从根节点开始,
* 先计算当前节点的左子节点与右子节点的高度,然后判断高度差是否>1
* 如果>1,则直接返回false;
* 如果<=1,则以左子结点和右子节点为新的父节点,继续递归判断;
* @param root
* @return
*/
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
int leftHeight = findHeightByNode(root.left); //左子树高度
int rightHeight = findHeightByNode(root.right); //右子树高度
if (Math.abs(leftHeight - rightHeight) > 1) {
return false;
}else {
boolean leftEnd = isBalanced(root.left);//继续判断左子树的左右子树
boolean rightEnd =isBalanced(root.right); //继续判断右子树的左右子树
if (leftEnd == false || rightEnd == false) {
return false;
}
}
return true;
}
/**
* 求出指定节点的高度
* 只能先递归向下,然后回溯,回溯时累加求出高度;
* 公式就是:当前node节点的高度=【(node节点的左子树的高度)和(node节点的右子树的高度)的最大值】+1
* @param node
*/
public int findHeightByNode(TreeNode node) {
//公式:当前node节点的高度=【(node节点的左子树的高度)和(node节点的右子树的高度)的最大值】+1
if (node == null) {
return 0; //叶子结点的左右子节点为null,直接返回0,回溯之后叶子节点的高度为1;
}
TreeNode leftNode = node.left; //左子结点
TreeNode rightNode = node.right; //右子节点
int height = Math.max(findHeightByNode(leftNode), findHeightByNode(rightNode))+1;
return height;
}
·
思路2:
在计算节点的高度的回溯步骤中,就判断回溯的当前节点的左右子树是否是一个高度平衡二叉树、左右子树的高度差是否大于1,
1、如果左右子树都是一个高度平衡二叉树、且高度差小于等于1,则计算出当前节点的高度,继续回溯;
2、否则,则直接返回-1;
·
代码示例:
/**
* 在回溯的时候,就判断回溯的当前节点的左右子树是否是一个高度平衡二叉树、左右子树的高度差是否大于1,
* 如果左右子树都是一个高度平衡二叉树、且高度差小于等于1,则计算出当前节点的高度,继续回溯;
* 否则,则直接返回-1;
*/
public int findHeightAndBalanced(TreeNode node) {
//公式:节点的高度= 左子树的高度 和 右子树的高度 的最大值+1;
if (node == null) {
return 0;
}
//当前节点的左子树的高度:
int leftHeight = findHeightAndBalanced(node.left);
//当前节点的右子树的高度:
int rightHeight = findHeightAndBalanced(node.right);
//如果已经有某个部位的子树不平衡了,则整体便是不平衡;
//如果左右子树的高度差>1,则便是一个不平衡二叉树;
if (leftHeight == -1 || rightHeight == -1 || Math.abs(leftHeight-rightHeight)>1) {
return -1;
}
//否则,才求出当前节点的高度:
int currHeight = Math.max(leftHeight,rightHeight) + 1;
return currHeight;
}
public boolean isBalanced(TreeNode root) {
int heightAndBalanced = findHeightAndBalanced(root);
if (heightAndBalanced == -1) {
return false;
}else{
return true;
}
}
·
总结:
思路1:自上往下,先求左右子树高度,再判断平衡;
- 如果从根节点开始,
- 先计算当前节点的左子节点与右子节点的高度,然后判断高度差是否>1
- 如果>1,则直接返回false;
- 如果<=1,则以左子结点和右子节点为新的父节点,继续往下递归判断;
这种是先求出左右子节点的高度,再判断是否是平衡的,然后继续往下递归(先求高度、再判断)。
这种是自顶向下的递归,求每个节点的高度的时候遍历了一回,判断是否是平衡二叉树的时候又遍历了一回,时间复杂度:O()
·
思路2:自下往上回溯时,在计算每个节点的高度的同时,便判断了其左右子树是否是平衡的;
在计算节点的高度的回溯步骤中,就判断回溯的当前节点的左右子树是否是一个高度平衡二叉树、左右子树的高度差是否大于1,
- 1、如果左右子树都是一个高度平衡二叉树、且高度差小于等于1,则计算出当前节点的高度,继续回溯;
- 2、否则,则直接返回-1;
对于每个节点,只会被遍历一次;因此时间复杂度:O(n);