Leetcode—110: 平衡二叉树(两种解法)

平衡二叉树的高效判断方法
这篇博客探讨了如何判断一个二叉树是否是高度平衡的。首先,介绍了直接通过递归计算节点高度差的方法,但由于返回值是高度而非高度差,导致无法正确计算。接着,提出了改进的解决方案,即在`getHeightValue()`方法中计算每个节点的高度,并在`isBalanced()`方法中判断高度差。当根节点的左右高度差大于1时,直接返回false,减少了不必要的递归调用,提高了效率。最后,通过对比两种方法,展示了优化后的方案能有效减少栈帧的开辟,提高代码执行效率。

题目描述:

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
在这里插入图片描述
分析:

平衡二叉树的定义就是要求每个节点的左右两棵子树的高度差的绝对值不超过1,所以问题的关键就是需要求出每个节点的高度差,然后判断。

思路一:

考虑的关键:!!!
一开始我思考能不能直接通过一个递归函数就把每一个节点的高度差计算出来,但是通过实践以及思考,发现:计算高度差必须先求出左右子树的高度,然后做差!如果直接将递归函数返回高度差,上一层的节点就没有办法计算高度差了(因为计算高度差必须知道左右子树的高度,而方法的返回值是高度差!!!)

具体解释过程如下图所示:
在这里插入图片描述
方法一的关键点:

  • 高度差:通过上面的分析,因此我采用定义一个类的成员变量(int num=0)来记录二叉树中所有节点中的最大高度差。
  • 递归方法( getHeightValue()):返回值为每个节点的高度,目的是为了在每次递归中能求每个节点的高度差,高度差变量(num)就镶嵌在递归方法中。
  • isBalanced()方法:只需要判断高度差是否满足条件。

代码实现:

class Solution {
    //num表示整个树中所有节点的最大高度差 
    public  int num=0;
   //通过递归遍历每个节点的高度差,得到最大的
    public int getHeightValue(TreeNode root)
    {
        if(root==null)        {    return 0;      }
         //求左右子树的高度,然后做差
        int leftHeight=getHeightValue(root.left);
        int rightHeight=getHeightValue(root.right);
        if(num < Math.abs(leftHeight-rightHeight))
        { 
            num=Math.abs(leftHeight-rightHeight);
        }
        //返回值还是返回该节点为根的高度(即:左右子树的最大高度)
        return leftHeight>rightHeight?leftHeight+1:rightHeight+1;
    }
    public boolean isBalanced(TreeNode root) {
        if(root==null ){return true;}        
        getHeightValue(root);
        if(num > 1 || num<0){return false;}
        return true;
    }
}

运行结果:

注意:

我在一开始将num定义为static,然后代码就不能通过,还出现了这样的问题,见下图:
在这里插入图片描述
当时我很诧异,还以为是leetcode出现问题了,然后刷新一直还是这样!!

通过一段时间的挣扎,总算明白为什么会是这样!!

原因:

  • 静态变量(num)在实例方法getHeightValue()中每次被改变,不同的对象使用它就会使用的是上一个对象改变的静态变量(num)。
  • 在点击“执行代码”按钮的时候,只跑一个测试用例,当然也只生成一个实例对象,所以如上图所示结果是对的!
  • 点击“提交”按钮,leetcode会将后台所有的测试用例都跑一遍,又因为我的代码是实例方法,所以前面的对象改变了静态变量(num)的值后,后面测试用例的对象在使用静态变量(num)时,其实使用的是上一个对象改变后的num值。因此出现上图的结果是错的!

思路二:

这种方法是参考大佬的!效率大大提升,在一定程度上减少了栈帧的开辟(递归)! 一块来学习一下。

方法:

  • getHeightValue():递归求二叉树中每个节点的高度
  • isBalanced():主要是来判断高度差的。
    • root=null:返回true
    • 如果根节点的左右高度差大于1:直接返回false;此处就是减少递归的关键所在!!减少了内存的开辟提高了效率。(因为根节点的高度差不满足平衡二叉树的要求就没有必要考虑其他子节点了。
    • 根节点的左右高度差小于1:继续判断其他节点的高度差
class Solution {
    //求二叉树中每个节点的高度
    public int getHeightValue(TreeNode root)
    {
        if(root==null)
        {
            return 0;
        }
         //分别求该节点左右子树的高度
        int leftHeight=getHeightValue(root.left);
        int rightHeight=getHeightValue(root.right);
        
        return leftHeight>rightHeight?leftHeight+1:rightHeight+1;
    }
    
    public boolean isBalanced(TreeNode root) {
        if(root==null)
        {
            return true;
        }
        //如果根节点的左右高度差不小于1,直接返回false
       if(Math.abs(getHeightValue(root.right)-getHeightValue(root.left))>1)
       {
           return false;
       }
       
        //如果根节点的左右高度差小于1,那麽继续判断其他节点的高度差
       return isBalanced(root.left) && isBalanced(root.right);
          
    }
}

运行结果:
在这里插入图片描述
两种方法对比:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值