leetcode:判断一棵树是否为平衡二叉树

18 篇文章 0 订阅

题目来源:力扣

题目要求:

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

审题:

题目要求很简单,判断一棵树是否为平衡二叉树.根据平衡二叉树的定义,我们可以得出一棵平衡树的所有子节点构成的子树也一定为平衡树.这种递归的定义指引我们使用递归的方式来判断一棵树是否是平衡二叉树.
我们可以使用如下思路判断:如果以当前节点为根的子树不是平衡二叉树,则当前树一定不是平衡二叉树.否则,我们需要计算判断其左子树与右子树是否为平衡二叉树,如果其中之一不是,则当前子树不是平衡二叉树.否则继续递归检查,直至底层.我们知道判断一棵树是否是平衡二叉树需要我们分别计算左子树高度与右子树高度,而这种自顶向上的递归方式中,我们在计算所有节点树高的过程中,存在大量的重复计算.因为每一个节点会在其上所有祖宗节点的高度计算中,多次重复计算其自身高度.看到这里,可能有人想到了计算原文题与子问题的求解中存在重复的计算部分,那么是不是要用动态规划了?其实大可不必,我们仔细分析便可发现,如果我们采用自底向上的思路,则不用动态规划便可轻松解决.因为使用自底向上的思路,我们相当于对节点进行后序遍历,所有节点仅需计算一次其树高,不存在重复计算的问题.自底向上判断平衡二叉树与自顶向下一致,如果以当前节点为根的子树不是平衡二叉树,则该树不是平衡二叉树.否则我们向上检查其父节点是否平衡二叉树.

回顾一下我们的分析过程:

  • 我们首先根据平衡二叉树的递归定义得出,要判断一棵树是否是平衡的,可以采用递归的方法
  • 我们发现,当使用先序遍历方式检查每一节点是否是平衡子树时,对各节点树高的计算中存在大量重复计算.
  • 使用后序遍历方式检查每一节点是否是平衡子树时,不存在对树高的重复计算,每一节点仅需计算一次树高.

因此我们使用后序遍历方式检查每一节点,判断当前树是否是平衡树.如果发现任意节点不平衡,则其后递归直接返回即可.

java算法实现:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    boolean balanced = true;
    //遍历每一子节点,检查以当前子节点为根的树是否为平衡树,如果发现某一子树不平衡,则该棵树不平衡;
    //时间复杂度O(N),需要遍历每一个子节点
    //空间复杂度为树的最大深度,当树平衡时,为O(lgN),最坏情况下,为O(N)
    private int depth(TreeNode x){
        if(x == null || !balanced) //如果balance为false, 则后续直接返回
            return 0;
        int depthLeft = depth(x.left);
        int depthRight = depth(x.right);
        if(Math.abs(depthLeft-depthRight) > 1)
            balanced = false;
        return Math.max(depthLeft, depthRight) + 1;
    }

    public boolean isBalanced(TreeNode root) {
        depth(root);
        return balanced;
    }
}

在上面的实现中,我们使用额外的boolean变量balanced纪录当前是否发现不平衡子树,在参考其他大佬的题解中,发现可是省略这一布尔变量,由于树的高度不会小于0,因此我们可以返回-1表示当前子树不平衡,如果当前节点的任意子树高度为-1,则该树的高度也为-1.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private int depth(TreeNode x){
        if(x == null)
            return 0;
        int depthLeft = depth(x.left);
        if(depthLeft == -1)
            return -1;
        int depthRight = depth(x.right);
        if(depthRight == -1)
            return -1;

        if(Math.abs(depthLeft-depthRight) > 1) //如果树不平衡,我们返回-1作为树高.
            return -1;
        else
            return Math.max(depthLeft, depthRight) + 1;
    }

    public boolean isBalanced(TreeNode root) {
        return depth(root) != -1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值