1.题目描述:
给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。
2.自顶向下递归:
判断当前节点左右两子树的高度差绝对值是否超过1,也就是判断当前节点是否平衡,随后递归判断各个节点是否平衡。左右子树的高度差计算由leetcode104. 二叉树的最大深度给出。递归三步骤,①递归终止条件:root = null,返回true。②每级递归需要做什么:判断当前节点是否平衡。③返回值:若当前节点不平衡返回false,若当前节点平衡递归返回当前节点的左右节点是否平衡。代码如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null) return true;
if(Math.abs(height(root.left) - height(root.right)) <= 1) return isBalanced(root.left) && isBalanced(root.right);
else return false;
}
public int height(TreeNode curNode) {
return curNode == null ? 0 : Math.max(height(curNode.left),height(curNode.right)) + 1;
}
}
将递归的二、三步合并:
return Math.abs(height(root.left) - height(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);
复杂度分析:
在判断当前节点是否平衡时,会调用当前节点子节点的height方法,而height会递归走遍其下所有节点,也就是说当前节点的深度若为n,它会被他之前所有的父节点调用即共被调用n次。大部分的节点height被重复调用。以满二叉树为例,时间复杂度近似为nlog2n,最坏情况二叉树为链表时,一共遍历n * (n - 1) / 2次,时间复杂度为O(n^2)。空间复杂度由于一次递归层级最大为n,所以为O(n),这里没有算入height递归的空间复杂度,有待商榷。
3.自底向上递归:
在递归计算节点height高度的过程中,直接判断其下节点中是否出现不平衡节点,若出现不平衡节点则直接返回false及时止损,但程序还是完整遍历所有节点,也就是只需要调用root节点的height方法即可遍历所有节点,自底向上判断所有节点是否平衡。时间复杂度和空间复杂度容易判断,均为O(n)。方法的写法有多种,举两个如下:
class Solution {
boolean flag = true;
public boolean isBalanced(TreeNode root) {
depth(root);
return flag;
}
public int depth(TreeNode curNode){
if(curNode == null) return 0;
int l = depth(curNode.left);
int r = depth(curNode.right);
if(Math.abs(l - r) > 1) flag = false;
return Math.max(l,r) + 1;
}
}
class Solution {
public boolean isBalanced(TreeNode root) {
return height(root) >= 0;
}
public int height(TreeNode root) {
if (root == null) return 0;
int l = height(root.left);
int r = height(root.right);
if (l == -1 || r == -1 || Math.abs(l - r) > 1) return -1;
else return Math.max(l,r) + 1;
}
}
4.二刷递归:
class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
if (Math.abs(depth(root.left) - depth(root.right)) > 1) return false;
return isBalanced(root.left) && isBalanced(root.right);
}
public int depth(TreeNode root) {//借助深度差来判断
if (root == null) return 0;
return 1 + Math.max(depth(root.left), depth(root.right));
}
}
自底向上:在求深度的同时直接加入平衡二叉树的定义判断。
class Solution {
boolean flag = true;
public boolean isBalanced(TreeNode root) {
depth(root);
return flag;
}
public int depth(TreeNode root) {
if (root == null) return 0;
int left = depth(root.left);
int right = depth(root.right);
if (Math.abs(left - right) > 1) {
flag = false;
return 0;//直接返回,不走完深度的全程判断
}
return Math.max(left, right) + 1;
}
}