平衡二叉树

一、需求

  • 输入一棵二叉树的根节点,判断该树是不是平衡二叉树。
  • 如果某二叉树中任意节点的左右子树的深度相差不超过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 。

二、前序遍历法

2.1  思路分析

  1. 上一篇我们求解了关于二叉树的最大深度,基于此原理,在这里求二叉树任意节点的深度;
  2. 根据前序遍历原理,先判断当前节点的左、右子树的深度是否满足平衡二叉树要求,然后递归判断当前节点的左子树,当前节点的右子树;

2.2  代码实现

class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root == null) return true;
        //判断当前节点、当前节点左子树、当前节点右子树是否平衡
        int res = Math.abs(depth(root.left) - depth(root.right));
        return res <= 1 && isBalanced(root.left) && isBalanced(root.right);
    }
    //求任意一个节点的深度
    public int depth(TreeNode node) {
        if(node == null) return 0;
        return Math.max(depth(node.left), depth(node.right)) + 1;
    }
}

2.3  复杂度分析

  • 时间复杂度为O(Nlog_2N),N为二叉树的节点个数,判断是否为平衡二叉树需遍历所有节点;
  1. 最坏情况下为满二叉树,计算其深度的时间复杂度为O(N),N为满二叉树的节点个数;
  2. 第一层计算根节点root深度需计算N次,第二层计算root.left和root.right各需计算(N-1)/2次,依次类推,到最后一层需计算(N+1)/2次,这样每一层最少计算(N+1)/2次,最多计算N次;
  3. 故总的时间复杂度是层数*每一层的复杂度,即为O(Nlog_2N)
  • 空间复杂度为O(N),最差情况下,当树退化为链表时,递归需要使用O(N)的栈空间;

三、后序遍历法1

3.1  思路分析

  1. 上述方法中要遍历每一个节点,然后计算当前节点左子树的深度和右子树的深度,直到某一节点的深度之差不满足平衡二叉树的条件时返回false,否则遍历所有节点后true;
  2. 上述方法的缺点在于计算每个节点的深度时,存在大量的重复计算,比如计算根节点的深度需要计算左子树和右子树的深度,若根节点符合条件,那么又要重新计算左子树深度;
  3. 为了克服上述缺点,利用后序遍历,从底向上判断,将每次计算的left和right节点深度的最大值通过加1返回到上一层节点,这样避免重复计算;

3.2  代码实现

class Solution {
    public boolean isBalanced(TreeNode root) {
        return recur(root) != -1;
    }
    //规定非平衡二叉树时,返回-1
    public int recur(TreeNode root) {
        if(root == null) return 0;
        int left = recur(root.left);
        //若左子树就不是平衡二叉树,直接返回
        if(left == -1) return -1;
        int right = recur(root.right);
        //若右子树不是平衡二叉树
        if(right == -1) return -1;
        //若当前节点下是平衡二叉树,那么返回当前节点的深度,作为上一层的left或right
        //不是平衡二叉树则返回-1
        return Math.abs(left-right) <= 1 ? Math.max(left,right) + 1 : -1;
    }
}

四、后序遍历法2

4.1  思路分析

  1. 这是按照第一种方法思路写的,第一种是前序遍历,这里使用后序遍历,时间复杂度和空间复杂度与方法一相同,效率贼低;

4.2  代码实现

class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root == null) return true;
        boolean left = isBalanced(root.left);
        boolean right = isBalanced(root.right);
        boolean res = Math.abs(depth(root.left) - depth(root.right)) <= 1 ? true : false;
        return left && right && res;
    }
    //求任意一个节点的深度
    public int depth(TreeNode node) {
        if(node == null) return 0;
        return Math.max(depth(node.left), depth(node.right)) + 1;
    }
}

五、学习地址

作者:Krahets

链接:https://leetcode-cn.com/problems/ping-heng-er-cha-shu-lcof/solution/mian-shi-ti-55-ii-ping-heng-er-cha-shu-cong-di-zhi/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值