《剑指offer》刷题——【面试中的各项能力】面试题55:二叉树的深度(java实现)

(一) 题目一:二叉树的深度

一、题目描述

输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长
路径的长度为树的深度。

二、题目分析

  • 若一棵树只有一个节点,深度=1;
  • 若根节点只有左子树没有右子树,深度=左子树的深度+1
  • 若根节点只有右子树没有左子树,深度=右子树的深度+1
  • 若根节点既有左子树又有右子树,深度=max(左子树深度,右子树深度)+1

三、代码实现

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public int TreeDepth(TreeNode root) {
        //输入有误
        if(root==null){
            return 0;
        }
        //递归左子树深度
        int left = TreeDepth(root.left);
        //递归右子树深度
        int right = TreeDepth(root.right);
        //返回左子树或右子树深度较大的一个加一
        return (left > right)? (left + 1):(right + 1);
    }
}

(二)题目二:平衡二叉树

一、题目描述

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

二、题目分析

方法一:递归——重复遍历

  • 遍历树的每一个节点时,调用TreeDepth得到每个节点的左、右子树的深度
  • 若每个节点的左、右子树的深度相差不超过1,即为平衡二叉树
public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
        //输入有误
        if(root==null){
            return true;
        }
        //左子树的深度
        int left = TreeDepth(root.left);
        //右子树的深度
        int right = TreeDepth(root.right);
        //左右子树差
        int diff = left - right;
        //深度差超过1,则不是平衡二叉树
        if(diff>1 || diff<-1){
            return false;
        }
        //深度差不超过1,则遍历左子节点 右子节点
        return IsBalanced_Solution(root.left) && IsBalanced_Solution(root.right);
    }
    /**
    *求树的深度
    */
    public int TreeDepth(TreeNode root) {
        //输入有误
        if(root==null){
            return 0;
        }
        //递归左子树深度
        int left = TreeDepth(root.left);
        //递归右子树深度
        int right = TreeDepth(root.right);
        //返回左子树或右子树深度较大的一个加一
        return (left > right)? (left + 1):(right + 1);
    }
}
  • 存在问题:重复遍历节点多次,时间效率不高

方法二:每个节点只遍历一次

  • 后序遍历(遍历到根节点时,已经遍历完左右节点了)
  • 遍历某个节点的左、右子节点后,根据左右深度,确定是否为平衡,并得到当前节点的深度
  • 当最后遍历到树的根节点时,也就能判断整棵树是不是平衡二叉树
public class Solution {
    public boolean IsBalanced_Solution(TreeNode root) {
       
        int depth = 0;//树的深度
        return IsBalanced(root, depth);
    }
    
    /**
    *判断二叉树是否平衡,并同时记录深度
    */
    public boolean IsBalanced(TreeNode root , int depth){
        //空树
        if(root==null){
            depth = 0;
            return true;
        }
        int left=0;
        int right=0;//左右子树深度
        //如果左右节点平衡
        if(IsBalanced(root.left,left) && IsBalanced(root.right, right)){
            //求左右子树深度差
            int diff = left-right;
            if(diff<=1 && diff>=-1){
                //当前节点的深度为左右深度大的一个的深度+1
                depth = 1 +(left>right ? left:right);
                return true;
            }
        }
        //若左右节点不平衡,则不是平衡二叉树
        return false;
    }
}

在这里插入图片描述

上述实现存在问题及解决方案:=

在c或c++中我们可以给递归的子过程中传入左右子树的高度的指针,当子过程回溯时,我们就可以
拿到改变后的值,而这种效果得益于指针的优势。而在Java中只有值传递,子过程改变的值,在父
过程中是看不见,子过程改变仅仅是实参的副本,实参本身是不发生变化的。所以我们要定义一对
象来持有深度值,这样子过程通过引用修改对象的成员变量时,父过程中的引用由于与实参(该引
用)的副本指向同一个对象,故而是可见的。

public class Solution {
    /**
    * 定义一个深度对象,递归子过程通过引用、修改对象的成员变量时,
    父过程中的引用由于与实参的副本指向同一个对象,子过程改变父过程可以看见
    */
    public static class DepthHolder{
    int depth=0;
    }
    
    public boolean IsBalanced_Solution(TreeNode root) {
        
        //空树
        if(root==null){
            return true;
        }
        //实例化深度对象
        DepthHolder depthHolder = new DepthHolder();
        return IsBalanced(root, depthHolder);
    }
    
    /**
    *判断二叉树是否平衡,并同时记录深度
    */
    public boolean IsBalanced(TreeNode root , DepthHolder depthHolder){
        //空树
        if(root==null){
            depthHolder.depth = 0;
            return true;
        }
        //实例化深度对象
        DepthHolder leftDepth= new DepthHolder();
        //实例化深度对象
        DepthHolder rightDepth = new DepthHolder();
        int right=0;//左右子树深度
        //如果左右节点平衡
        if(IsBalanced(root.left,leftDepth) && IsBalanced(root.right, rightDepth)){
            //求左右子树深度差
            int diff = leftDepth.depth - rightDepth.depth;
            if(diff<=1 && diff>=-1){
                //当前节点的深度为左右深度大的一个的深度+1
                depthHolder.depth = 1 +(leftDepth.depth>rightDepth.depth ? leftDepth.depth:rightDepth.depth);
                return true;
            }
        }
        //若左右节点不平衡,则不是平衡二叉树
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值