数据结构与算法--二叉树的深度问题

二叉树的深度
  • 题目:输入一颗二叉树的根,求该树的深度。从根节点到叶子节点一次进过的节点形成的一条路径,最长的路径的长度为树的深度。
  • 如下图中二叉树的额深度4,因为从根节点A到叶子节点的路径中有4个节点A B E J

在这里插入图片描述

  • 问题中定义了一种树深度的计算规则,我们根据这个定义去得到树所有的路径,也就得到了最长的额路径。在我们之前的文章:数据结构与算法–面试必问AVL树原理及实现文章中,我们对二叉搜索树的具体实现方案有详细的说明,其中二叉搜索树平衡条件是左右子树的高度差不能超过1 ,和我们当前要求是一致的,我们借鉴其中高度求值的思路
  • 分析
    • 二叉树还是递归的思路,既然我们需要求高度差
    • 分别递归求左右子树的高度,在求解
    • 同二叉树的后续遍历一样递归,只不是现在将遍历元素值,变为现在遍历高度并累加
    • 递归思路,按最简单的节点分析,当只有一个左右子树,那么递归到left 高度0, 递归到right 高度0
    • 那么此时根节点高度 height= Math.max(left + right) + 1
  • 经如上分析有如下代码
/**
 * 求二叉树的深度
 * @author liaojiamin
 * @Date:Created in 17:43 2021/6/24
 */
public class BinaryDepth {

 public static void main(String[] args) {
        BinaryNode node1 = new BinaryNode(null, null, null);
        BinarySearchTree tree1 = new BinarySearchTree();
        Random random = new Random();
        int[] array = new int[]{1,27,37,19,514,216,118,320,426,228};
        for (int i = 0; i < array.length; i++) {
            node1 = tree1.insert(Integer.valueOf(random.nextInt(20)), node1);
        }
        System.out.println(depthBinary(node1));
        tree1.printTree(node1);
    }
/**
     * 递归方式求解,
     *  左节点为空则,左高度为left = 0,总高度为 left + 1
     *  右节点为空则,右高度为right = 0,总高度为 right + 1
     *  递归到子节点,赋值left= 0,right = 0,接着一层一层递归上到根节点。
     * */
    public static Integer depthBinary(BinaryNode tree){
        if(tree == null){
            return 0;
        }
        int left = depthBinary(tree.getLeft());
        int right = depthBinary(tree.getRight());
        return left > right ? left + 1 : right + 1;
    }
}
变种题型-求平衡二叉树
  • 题目:输入一颗二叉树的根,判断该树是否平衡二叉树。如果某二叉树中任意左右节点的树深度不超过1 ,那么他就是一颗平衡二叉树。
  • 还是在刚才二叉搜索树的文中,我们求高度的目的就是需要再平衡二叉树,使得经过修改的二叉树能够达到二叉搜索树的结构特性。既然在以上方法中我们得到了高度,那么可以在逻辑上修改就能求解本问题
  • 分析:
    • 通上题中,分别递归求解left, right
    • 得到left, right高度,求差值 > 1 ,则不是平衡
  • 如上分析有如下代码:
/**
 * 求二叉树的深度
 * @author liaojiamin
 * @Date:Created in 17:43 2021/6/24
 */
public class BinaryDepth {

    public static void main(String[] args) {
        BinaryNode node1 = new BinaryNode(null, null, null);
        BinarySearchTree tree1 = new BinarySearchTree();
        Random random = new Random();
        int[] array = new int[]{1,27,37,19,514,216,118,320,426,228};
        for (int i = 0; i < array.length; i++) {
            node1 = tree1.insert(Integer.valueOf(random.nextInt(20)), node1);
        }
        System.out.println(validateBalancedTree(node1));
        tree1.printTree(node1);
    }


    /**
     * 一棵二叉树中所有节点对应的左右子树高度差不超过1 ,那么说明这棵树是平衡二叉树
     * 递归判断是否平衡树
     * */
    public static boolean validateBalancedTree(BinaryNode tree){
        if(tree == null){
            return true;
        }
        int left = depthBinary(tree.getLeft());
        int right = depthBinary(tree.getRight());
        int diff = Math.abs(left - right);
        if(diff > 1){
            return false;
        }
        return validateBalancedTree(tree.getLeft()) && validateBalancedTree(tree.getRight());
    }
   /**
     * 递归方式求解,
     *  左节点为空则,左高度为left = 0,总高度为 left + 1
     *  右节点为空则,右高度为right = 0,总高度为 right + 1
     *  递归到子节点,赋值left= 0,right = 0,接着一层一层递归上到根节点。
     * */
    public static Integer depthBinary(BinaryNode tree){
        if(tree == null){
            return 0;
        }
        int left = depthBinary(tree.getLeft());
        int right = depthBinary(tree.getRight());
        return left > right ? left + 1 : right + 1;
    }
}

  • 以上代码比较简单,但是存在问题是节点会被重复遍历,当遍历第二层节点 B,C时候,会遍历H I J节点,同样 遍历D,E F G时候还是会重复遍历H I J 节点,类似斐波那契数量的递归求解一样,重复的遍历会时间复杂度指数级增长,当树高度越大,重复遍历的次数越多。我们需要找到更优方案
每个节点遍历一次解法
  • 我们之前是为了求深度,才直接递归左右节点,然后在判断,既然我们都遍历了求出了深度,那么能不能同时标记每一个节点的深度呢
  • 分析
    • 还是按刚才思路,分别遍历左右子树求高度,我们还是按最简单的元素来分析递归的情况
    • 当左右子树都只有一个节点,遍历左子树,left = 1, 遍历右子树 right = 1
    • 此时不同的点我们更新当前根节点的高度height = Math.max(left,right) + 1
    • 依次递归到根节点
    • 以上思路还是二叉树的后续遍历的思想,左右根,一边遍历,一边计算高度,一边更新节点高度信息
    • 更新完根的高度后,在判断是否满足 left - right > 1,放回对应值,以跳出递归
  • 如是哪个分析有如下代码
/**
 * 求二叉树的深度
 * @author liaojiamin
 * @Date:Created in 17:43 2021/6/24
 */
public class BinaryDepth {

    public static void main(String[] args) {
        BinaryNode node1 = new BinaryNode(null, null, null);
        BinarySearchTree tree1 = new BinarySearchTree();
        Random random = new Random();
        int[] array = new int[]{1,27,37,19,514,216,118,320,426,228};
        for (int i = 0; i < array.length; i++) {
            node1 = tree1.insert(Integer.valueOf(random.nextInt(20)), node1);
        }
        System.out.println(validateBalancedTreeHeight(node1));
        tree1.printTree(node1);
    }

 /**
     * 直接后序遍历,同时标记深度
     * */
    public static boolean validateBalancedTreeHeight(BinaryNode tree){
        if(tree == null){
            return true;
        }
        boolean left = validateBalancedTreeHeight(tree.getLeft());
        boolean right = validateBalancedTreeHeight(tree.getRight());
        int leftHeight = tree.getLeft()!= null ? tree.getLeft().getHeight(): 0;
        int rightHeight = tree.getRight() != null ? tree.getRight().getHeight() : 0;
        tree.setHeight(1 + Math.max(leftHeight, rightHeight));
        if(left && right){
            int diff = Math.abs(leftHeight - rightHeight);
            if(diff > 1){
                return false;
            }else {
                return true;
            }
        }
        return false;
    }
 }
  • 以上方法后续遍历的方式遍历整个二叉树,遍历同时求深度,判断平衡,当遍历到树根,也就得树是否平衡的二叉树。

上一篇:数据结构与算法–数字在排序数组中出现次数
下一篇:数据结构与算法–数组中出一次的数字

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值