平衡二叉树
题目描述
力扣链接🔗
题目分析
高度和深度的概念在二叉树概述中。此题注意:而根节点的高度就是这棵树的最大深度。
代码
递归法
- 明确递归函数的参数和返回值
参数:当前传入节点。
返回值:以当前传入节点为根节点的树的高度。
那么如何标记左右子树是否差值大于1呢?如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了。 - 明确终止条件
递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0。 - 单层循环
求当前左子树和右子树的高度差,如果相差大于一,那么就已经不是平衡二叉树了,此时需要将结果返回-1,标志此时已经不是平衡二叉树。如果上一次递归返回的结果为-1,那么直接返回-1,表示不是平衡二叉树。
/**
* 后序递归法
* @param root
* @return
*/
public boolean isBalanced(TreeNode root) {
return getHeight(root) == -1 ? false : true;
}
// -1表示此时高度差已经大于1
public int getHeight(TreeNode root) {
if (root == null) {
return 0;
}
int leftHeight = getHeight(root.left); // 左
if (leftHeight == -1) return -1;
int rightHeight = getHeight(root.right);// 右
if (rightHeight == -1) return -1;
if (Math.abs(leftHeight - rightHeight) > 1) { // 中
return -1; // 左右子树高度相差大于1,返回-1
} else {
return 1 + Math.max(leftHeight, rightHeight); // 左右子树高度相差小于1,此节点作为根节点的高度就为最大深度
}
}
先序也可以
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
if (isBalanced(root.left) == false) return false;
if (isBalanced(root.right) == false) return false;
int left = traversal(root.left);
int right = traversal(root.right);
return Math.abs(left - right) <= 1;
}
public int traversal(TreeNode root) {
if (root == null) {
return 0;
}
int left = traversal(root.left);
int right = traversal(root.right);
return 1 + Math.max(left, right);
}
迭代法
定义一个求深度的方法,每次遍历一个节点就求其深度,然后再按照上述递归法思路判断左右孩子是否相差1。
/**
* 迭代法(时间复杂度O(n ^ n))
*
* @param root
* @return
*/
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
// 然后再用栈来模拟前序遍历,遍历每一个节点的时候,再去判断左右孩子的高度是否符合
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
int leftHeight = 0, rightHeight = 0;
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
leftHeight = getHeight(node.left);
rightHeight = getHeight(node.right);
if (Math.abs(leftHeight - rightHeight) > 1) { // 中
return false;
} else {
if (node.right != null) isBalanced(node.right); // 右(空节点不入栈)
if (node.left != null) isBalanced(node.left); // 左(空节点不入栈)
}
}
return true;
}
/**
* 层序求深度
*
* @param root
* @return
*/
public int getHeight(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int height = 0;
while (!queue.isEmpty()) {
int len = queue.size();
height++;
while (len > 0) {
TreeNode node = queue.poll();
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
len--;
}
}
return height;
}
求深度适合用前序遍历,而求高度适合用后序遍历。