平衡二叉树:每一个节点的左右子树的高度差不超过1.
对于一颗树,它是一个平衡二叉树需要满足三个条件:它的左子树是平衡二叉树,它的右子树是平衡二叉树,它的左右子树的高度差不大于1。
本题同:剑指39.平衡二叉树
本题的递归关键是找好递归的返回值。
☆☆☆思路1:自顶向下的递归,类似于前序遍历。借助一个获取树深度的递归函数。
思路1的缺点是在判断上层节点时,会多次重复遍历下层节点,增加了不必要的开销,会重复计算多次子树高度。
☆☆☆☆思路2【最优解】:自底向上的递归,类似于后序遍历。边求高度边判断,对于每个节点,高度height只会被调用一次。
☆☆☆☆思路3:新定义一个内部类,使得递归的返回值包括 当前树是否是BST 和 当前树的高度 这两个信息
class Solution { // 返回值应该包含当前树是否是BST和当前树的高度这两个信息 private class ReturnNode{ boolean isB; int depth; public ReturnNode(int depth, boolean isB) { this.depth = depth; this.isB = isB; } } public boolean isBalanced(TreeNode root) { /** * 方法1:自顶向下递归,类似于前序遍历 * 时间复杂度:O(n^2) */ /* if (root == null) return true; // Step1:对于当前遍历的节点进行判断 int l = treeDepth(root.left); int r = treeDepth(root.right); if (Math.abs(l - r) > 1) return false; // Step2:递归判断其左右子树是否平衡 return isBalanced(root.left) && isBalanced(root.right); */ /** * 方法2:自底向上,类似于后序遍历 * 时间复杂度O(n) */ return getDepth(root) != -1; /** * 方法3: * 参考博客:https://lyl0724.github.io/2020/01/25/1/ */ // return isBST(root).isB; } // 方法1,以下函数用来获取树的最大深度 private int treeDepth(TreeNode root) { if (root == null) return 0; return Math.max(treeDepth(root.left), treeDepth(root.right)) + 1; } // 方法2 自底向上,类似于后序遍历 private int getDepth(TreeNode root) { if (root == null) return 0; // Step1:先递归判断左右子树是否平衡 int left = getDepth(root.left); if (left == -1) return -1; int right = getDepth(root.right); if (right == -1) return -1; // Step2:再判断以当前节点为根的子树是否平衡 return Math.abs(left-right) > 1 ? -1 : Math.max(left, right) + 1; } // 方法3 private ReturnNode isBST(TreeNode root) { if (root == null) return new ReturnNode(0,true); //不平衡的情况有3种:左树不平衡、右树不平衡、左树和右树差的绝对值大于1 ReturnNode left = isBST(root.left); ReturnNode right = isBST(root.right); if (left.isB == false || right.isB == false) { return new ReturnNode(0,false); } if (Math.abs(left.depth - right.depth) > 1) { return new ReturnNode(0,false); } //不满足上面3种情况,说明平衡了,树的深度为左右俩子树最大深度+1 return new ReturnNode(Math.max(left.depth,right.depth) + 1, true); } }