剑指Offer面试题39(Java版):二叉树的深度
题目:输入一棵二叉树的根节点,求该数的深度。
从根节点到叶结点依次进过的结点(含根,叶结点)形成树的一条路径,最长路径的长度为树的深度。
比如。例如以下图的二叉树的深度为4。由于它从根节点到叶结点的最长的路径包括4个结点(从根结点1開始,经过2和结点5,终于到达叶结点7)
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
我们能够从还有一种角度来理解树的深度。
假设一棵树仅仅有一个结点,它的深度为1,假设根节点仅仅有左子树而没有右子树,那么树的深度应该是其左子树的深度+1.相同假设根节点仅仅有右子树而没有左子树,那么树的深度应该是其右子树+1.假设既有左子树又有右子树。那概述的深度就是左、右子树的深度的较大值加1.。
利用这个思路,我们能够用递归来实现代码:
//普通二叉树求深度
public int treeDepth(BinaryTreeNode root){
if(root == null)
return 0;
int nLeft = treeDepth(root.leftNode);
int nRight = treeDepth(root.rightNode);
return (nLeft > nRight)? (nLeft+1):(nRight+1);
}
假设公司对编程能力有较高的要求。面试官可能会追加一个与前面的问题相关但难度较大的问题,比方,应聘者做完上面的问题后,面试官追问:
题目二:输入一棵二叉树的根节点。推断该树是不是平衡的二叉树。假设某二叉树中随意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
须要反复遍历结点多次的解法,简单但不足以打动面试官
有了求二叉树的深度的经验之后再解决问题,我们非常easy就能想到一个思路:在遍历树的每一个结点的时候,调用函数TreeDepth得到它的左右子树的深度。假设每一个结点的左右子树的深度相差不超过1,依照定义它就是一棵平衡的二叉树。
这样的思路实现的代码例如以下:
//推断是否是一颗平衡二叉树
public boolean isBalanced(BinaryTreeNode root){
if(root ==null)
return true;
int left = treeDepth(root.leftNode);
int right = treeDepth(root.rightNode);
int diff = left - right;
if(diff > 1 || diff <-1)
return false;
return isBalanced(root.leftNode) && isBalanced(root.rightNode);
}
上面的代码固然简洁,但我们也注意到因为一个结点会被反复遍历多次,这样的思路的时间效率不高。
比如在函数isBalanced中输入上图中的二叉树,我们将首先推断根节点是不是平衡的。
此时我们网函数TreeDepth输入左子树的根节点时须要遍历结点4,5。7.接下来推断以结点2为根节点的子树是不是平衡树的时候。仍然会遍历结点4,5,7.毫无疑问,反复遍历同一个结点会影响性能。接下来我们寻找不须要反复遍历的算法。
每一个结点仅仅遍历一次的解法,正是面试官喜欢的算法
假设我们用后序遍历的方式遍历二叉树的每一个结点。在遍历一个结点之前我们就已经遍历了它的左右子树。仅仅要在遍历每一个结点的时候我们记录它的深度(某一节点的深度等于它到叶结点的路径的长度),我们就能够一边遍历一边推断每一个结点是不是平衡二叉树。
以下是这样的思路的实现代码:
//高效率的推断是否是一棵平衡二叉树
public boolean isBalanced2(BinaryTreeNode root){
int depth = 0;
return isBalanced2(root,depth);
}
public boolean isBalanced2(BinaryTreeNode root,int depth){
if(root == null){
depth = 0;
return true;
}
int left = 0,right = 0;
if(isBalanced2(root.leftNode,left) && isBalanced2(root.rightNode,right)){
int diff = left-right;
if(diff <= 1 && diff >= -1){
depth = 1+(left > right?left : right);
return true;
}
}
return false;
}
在上面的代码中,我们用后序遍历的方式遍历整棵二叉树。在遍历某结点的左右子树结点之后,我们就能够依据它的左右子树的深度推断它时不时平衡的,并得到当前结点的深度。当最后遍历到树的根节点的时候,也就推断了整棵二叉树是不是平衡二叉树。
剑指Offer面试题39(Java版):二叉树的深度的更多相关文章
- 剑指offer面试题14(Java版):调整数组顺序使奇数位于偶数的前面
题目:输入一个整数数组.实现一个函数来调整该数组中数字的顺序.使得全部奇数位于数组的前半部分.全部偶数位于数组的后半部分. 1.基本实现: 假设不考虑时间复杂度,最简单的思路应该是从头扫描这个数组,每 ...
- C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解
剑指offer 面试题39:判断平衡二叉树 提交网址: http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...
- C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解
剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...
- 剑指offer面试题:输入某二叉树的前序遍历和中序遍历,输出后序遍历
二叉树的先序,中序,后序如何遍历,不在此多说了.直接看题目描述吧(题目摘自九度oj剑指offer面试题6): 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结 ...
- C++版-剑指offer 面试题6:重建二叉树(Leetcode105. Construct Binary Tree from Preorder and Inorder Traversal) 解题报告
剑指offer 重建二叉树 提交网址: http://www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6?tpId=13&tq ...
- 剑指offer面试题6:重建二叉树
1.题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树. public class Solution { public TreeNode reConstructBinaryTree(int ...
- 剑指offer——面试题7:重建二叉树
// 面试题7:重建二叉树 // 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输 // 入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1, // 2, ...
- 剑指Offer第36题—Java版
本题使用归并排序的思想,结合归并排序,写出的算法解. //数组中的逆序对 public static int InversePairs(int[] array){ if(array==null||ar ...
- [刷题] 剑指Offer 面试题7:重建二叉树
题目:输入某二叉树的前序遍历和中序遍历结果,重建该二叉树.(假设输入的前序和中序遍历结果中都不含重复数字) 思路 构建二叉树的两个函数:Construct().ConstructCore() Cons ...
随机推荐
- 远程调用服务框架-CXF(WebServic)
介绍 远程调用web服务,不需要自己编写具体代码,只需要调用作者给出的接口即可. 我们可以调用互联网上查询天气信息Web服务,然后将它嵌入到我们的程序(C/S或B/S程序)当中来,当用户从我们的网点看 ...
- ML技术 - 特征选择
1. 决策树中的特征选择 分类决策树是一种描述对实例进行分类的树型结构,决策树学习本质上就是从训练数据集中归纳出一组分类规则,而二叉决策树类似于if-else规则.决策树的构建也是非常的简单,首先依据 ...
- AsciidocFX编辑器小贴士
I. AsciidocFX支持UML生成: 要生成UML,记得要下载GRAPHVIZ,并配置GRAPHVIZ_DOT环境变量,路径是Graphviz\bin\dot.exe. II. Asciidoc ...
- R语言高性能编程(二)
接着上一篇 一.减少内存使用的简单方法1.重用对象而不多占用内存 y <- x 是指新变量y指向包含X的那个内存块,只有当y被修改时才会复制到新的内存块,一般来说只要向量没有被其他对象引用,就可 ...
- python基础-------模块与包(一)
模块与包 Python中的py文件我们拿来调用的为之模块:主要有内置模块(Python解释器自带),第三方模块(别的开发者开发的),自定义模块. 目前我们学习的是内置模块与第三方模块. 通过impor ...
- tornado的非异步阻塞模式
[优化tornado阻塞任务的三个选择] 1.优化阻塞的任务,使其执行时间更快.经常由于是一个DB的慢查询,或者复杂的上层模板导致的,这个时候首要的是加速这些任务,而不是优化复杂的webserver. ...
- Python之配置模块ConfigParser
http://docs.python.org/2/library/configparser.html http://www.cnblogs.com/sislcb/archive/2008/11/25/ ...
- PHP设计模式之工厂模式
工厂模式(Factory pattern)和单例模式一样,是另外一种创建型模式. 和单例模式不同的是,单例模式会创建和管理一个单独的类型的单一对象,工厂模式则是用于创建多种不同类型的类的多个对象. 工 ...
- JavaScript学习笔记(七)——函数的定义与调用
在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...
- TensorFlow简易学习[1]:基本概念和操作示例
简介 TensorFlow是一个实现机器学习算法的接口,也是执行机器学习算法的框架.使用数据流式图规划计算流程,可以将计算映射到不同的硬件和操作系统平台. 主要概念 TensorFlow的计算可以表示 ...