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

二叉树的深度

  • 题目:输入一颗二叉树的根,求该树的深度。从根节点到叶子节点一次进过的节点形成的一条路径,最长的路径的长度为树的深度。
  • 如下图中二叉树的额深度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;}}
  • 以上方法后续遍历的方式遍历整个二叉树,遍历同时求深度,判断平衡,当遍历到树根,也就得树是否平衡的二叉树。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310332.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

进击谷歌:多线程下程序执行顺序怎么稳定不乱?

点击上方蓝字 关注我们面试官您好&#xff0c;我是来面试的您好&#xff0c;我是这次的面试官&#xff0c;先介绍一下自己把我是女孩&#xff0c;blala ....那问一个多线程的问题吧&#xff0c;在一个多线程的环境中&#xff0c;怎么能保证一系列方法的执行顺序呢&#xff1f;…

[Java基础]Set集合概述和特点

练习代码如下: package test21;import java.util.HashSet; import java.util.Set;public class SetDemo {public static void main(String[] args){Set<String> set new HashSet<String>();set.add("hello");set.add("world");set.add("…

深圳本次核酸检普筛怎么将个人信息和结果对应上??

前言 最近深圳疫情比较严重&#xff0c;好在上午新闻公布本次普筛都是阴性&#xff0c;期间我检查了三次&#xff0c;基本上每周测一次的样子&#xff0c;基本的检测非常快&#xff0c;只是需要筛查的人数太多&#xff0c;因此才有几公里的排队出现&#xff0c;期间也发现了一…

借助Redis完成延时任务

背景 相信我们或多或少的会遇到类似下面这样的需求&#xff1a;第三方给了一批数据给我们处理&#xff0c;我们处理好之后就通知他们处理结果。大概就是下面这个图说的。本来在处理完数据之后&#xff0c;我们就会马上把处理结果返回给对方&#xff0c;但是对方要求我们处理速度…

[Java基础]HashSet集合概述和特点

HashSet集合概述和特点: 练习代码如下: package HashSetPackage;import java.util.HashSet;public class HashSetDemo {public static void main(String[] args){HashSet<String> hs new HashSet<String>();hs.add("hello");hs.add("world")…

多亏我缓存技术过硬!疫情防控项目上线,我只用了5天!

先介绍下背景&#xff0c;我是武汉某O2O电商公司开发组长&#xff0c;疫情震中的我被老板要求7天之内上线《疫情防控热点图》项目&#xff0c;几个组员回老家断网&#xff0c;最终就2个人完成开发上线&#xff0c;满足了10w用户的高频访问。时间和人力都紧张&#xff0c;不能按…

数据结构与算法--有序数组中找出和为s的两个数字

有序数组中找和为s的两个数字 题目&#xff1a;输入一个递增排序的数组array&#xff0c; 和一个数字s&#xff0c; 在数组中找出两个数&#xff0c;使得这两个数的和是s&#xff0c;如果有多对&#xff0c;输出一对即可。 最简单方案 双循环&#xff0c;每次获取一个数据&a…

ABP框架使用拦截器动态配置租户过滤器

前言最近项目要求在ABP框架中根据TenantId是否为空来配置是否禁用租户过滤器。ABP自身给我我们禁用租户过滤器的两种方法官方文档https://aspnetboilerplate.com/Pages/Documents/Data-Filters方法一&#xff1a;使用工作单元using (_unitOfWorkManager.Current.DisableFilter(…

[Java基础]LinkedHashSet集合概述和特点

练习代码如下: package LinkedHashSetPack;import java.util.LinkedHashSet;public class LinkedHashSetDemo {public static void main(String[] args){LinkedHashSet<String> linkedHashSet new LinkedHashSet<String>();linkedHashSet.add("hello")…

数据结构与算法--翻转单词顺序

翻转单词顺序 题目&#xff1a;输入一个英文句子&#xff0c;翻转句子中的单词顺序&#xff0c;但是单词内的字符顺序不变&#xff0c;例如&#xff1a;I am a software engineer -> engineer software a am I 方案一&#xff1a;空间换时间 空间换时间方法&#xff0c;还…

在.NET Core中用最原生的方式读取Nacos的配置

背景 之前老黄写过一篇《ASP.NET Core结合Nacos来完成配置管理和服务发现》简单介绍了如何让.NET Core程序接入Nacos&#xff0c;之前的SDK里面更多的是对Nacos的Open API进行了封装以及对服务注册和发现的封装。配置这一块当时并没有过多的处理&#xff0c;用起来有时感觉不会…

[Java基础]TreeSet集合概述和特点

练习代码如下: package TreeSetPack;import java.util.TreeSet;public class TreeSetDemo {public static void main(String[] args){TreeSet<Integer> ts new TreeSet<Integer>();ts.add(10);ts.add(40);ts.add(30);ts.add(50);ts.add(20);ts.add(30);for (Inte…

.NET Core下的开源分布式任务调度系统ScheduleMaster-v2.0低调发布

从1月份首次公开介绍这个项目到现在也快4个月了&#xff0c;期间做了一些修修补补整体没什么大的改动。2.0算是发布之后第一个大的版本更新&#xff0c;带来了许多新功能新特性&#xff0c;也修复了一些已知的bug&#xff0c;在此感谢在博客、Issue和QQ群中提出各种意见的朋友&…

[Java基础]自然排序Comparable的使用

代码如下: package ComparablePack;public class Student implements Comparable<Student>{private String name;private int age;public Student() {}public Student(String name, int age) {this.name name;this.age age;}public String getName() {return name;}pu…

数据结构与算法--我们来玩丢手绢(约瑟夫环问题)

我们来玩丢手绢 昨天我们打扑克&#xff0c;今天我们丢手绢丢手绢我们都知道这个游戏&#xff0c;他的由来由约瑟夫 &#xff08;Josephus&#xff09;提出来的 据说著名犹太历史学家Josephus有过以下的故事&#xff1a;在罗马人占领乔塔帕特后&#xff0c;39 个犹太人与Jose…

后端开发都应该了解点接口的压力测试(Apache Bench版)

背景 小A&#xff1a;小B&#xff0c;最近调你的接口老是超时呀&#xff0c;8秒都还没返回结果&#xff0c;是不是有性能问题呀&#xff01;小B &#xff1a;我看看~~类似这样的对话&#xff0c;在现实中是时有发生的&#xff0c;不是特别严重的话&#xff0c;往往大家也不会去…

数据结构与算法--这个需求很简单怎么实现我不管(发散思维)

发散思维 程序员是一个高危职业&#xff0c;最近动不动就听到谁谁谁猝死&#xff0c;谁谁谁过劳晕倒&#xff0c;所以面对奇葩问题&#xff0c;我们要淡定&#xff0c; 开发中被产品虐&#xff0c;说的最多的一句话就是这个需求很简单&#xff0c;怎么实现我不管 找工作被面试…

[Java基础]比较器排序Comparator的使用

代码如下: package ComparablePack;public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public void setName(String name) {this…

手把手教你如何构建 WPF 官方开源框架源代码

本文转自林德熙的博客&#xff08;blog.lindexi.com&#xff09;导语从去年微软就将 WPF 开源了&#xff0c;差不多现在所有 WPF 的源代码都开源了。在学习框架的时候&#xff0c;我会做一些改动&#xff0c;期望能构建一个自己的版本进行测试。但是作为一个特别大的框架&#…