题目:输入一棵二叉树的根节点,求该数的深度。

从根节点到叶结点依次进过的结点(含根,叶结点)形成树的一条路径,最长路径的长度为树的深度。

比如。例如以下图的二叉树的深度为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版):二叉树的深度的更多相关文章

  1. 剑指offer面试题14(Java版):调整数组顺序使奇数位于偶数的前面

    题目:输入一个整数数组.实现一个函数来调整该数组中数字的顺序.使得全部奇数位于数组的前半部分.全部偶数位于数组的后半部分. 1.基本实现: 假设不考虑时间复杂度,最简单的思路应该是从头扫描这个数组,每 ...

  2. C++版 - 剑指offer 面试题39:判断平衡二叉树(LeetCode 110. Balanced Binary Tree) 题解

    剑指offer 面试题39:判断平衡二叉树 提交网址:  http://www.nowcoder.com/practice/8b3b95850edb4115918ecebdf1b4d222?tpId= ...

  3. C++版 - 剑指Offer 面试题39:二叉树的深度(高度)(二叉树深度优先遍历dfs的应用) 题解

    剑指Offer 面试题39:二叉树的深度(高度) 题目:输入一棵二叉树的根结点,求该树的深度.从根结点到叶结点依次经过的结点(含根.叶结点)形成树的一条路径,最长路径的长度为树的深度.例如:输入二叉树 ...

  4. 剑指offer面试题:输入某二叉树的前序遍历和中序遍历,输出后序遍历

    二叉树的先序,中序,后序如何遍历,不在此多说了.直接看题目描述吧(题目摘自九度oj剑指offer面试题6): 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结 ...

  5. C++版-剑指offer 面试题6:重建二叉树(Leetcode105. Construct Binary Tree from Preorder and Inorder Traversal) 解题报告

    剑指offer 重建二叉树 提交网址: http://www.nowcoder.com/practice/8a19cbe657394eeaac2f6ea9b0f6fcf6?tpId=13&tq ...

  6. 剑指offer面试题6:重建二叉树

    1.题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树. public class Solution { public TreeNode reConstructBinaryTree(int ...

  7. 剑指offer——面试题7:重建二叉树

    // 面试题7:重建二叉树 // 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输 // 入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1, // 2, ...

  8. 剑指Offer第36题—Java版

    本题使用归并排序的思想,结合归并排序,写出的算法解. //数组中的逆序对 public static int InversePairs(int[] array){ if(array==null||ar ...

  9. [刷题] 剑指Offer 面试题7:重建二叉树

    题目:输入某二叉树的前序遍历和中序遍历结果,重建该二叉树.(假设输入的前序和中序遍历结果中都不含重复数字) 思路 构建二叉树的两个函数:Construct().ConstructCore() Cons ...

随机推荐

  1. Struts2+Spring+Hibernate实现员工管理增删改查功能(一)之登录功能

    昨天的博客中我分享了个人关于ssh实现员工管理的框架整合,今天我在分享管理员登录功能的实现.  转载请注明出处"http://www.cnblogs.com/smfx1314/p/78013 ...

  2. php缓存模块apc可能导致php-fpm终止

    如果你的网站出现502错误.同时你网站中又使用了apc模块来做缓存处理.那么这篇文章兴许能帮到你. 首先,查看了php-fpm 的进程数. 发现php-fpm的进程数已经到达了php-fpm.conf ...

  3. JavaScript系列----AJAX机制详解以及跨域通信

    1.Ajax 1.1.Ajax简介 Ajax简介这一部分我们主要是谈一下ajax的起源,ajax是什么?因为这些是跟技术无关的.所以,大多细节都是一笔带过. Ajax的起源? Ajax一词源于2005 ...

  4. RobotFramework自动化测试环境配置

    现在工作是做自动化测试平台维护的,平台用的C#做的,主要是用来测试CMBRun项目,它是c/s结构的项目,而b/s结构的项目主要使用RF+Python来做.做这块之前听过自动化测试,身边的朋友也有做这 ...

  5. c# RSA加密和解密

    ");            Console.WriteLine(encodeString);            string decode = MyRSA.Decrypt(encode ...

  6. configure配置脚本的使用

    Linux下软件的安装一般由3个步骤组成: ./configure --host=arm-linux ... //配置 make //编译 make install //安装 若取消编译: make ...

  7. riot.js教程【五】标签嵌套、命名元素、事件、标签条件

    前文回顾 riot.js教程[四]Mixins.HTML内嵌表达式 riot.js教程[三]访问DOM元素.使用jquery.mount输入参数.riotjs标签的生命周期: riot.js教程[二] ...

  8. 第二个MapReduce

    大家在学习Hadoop的MapReduce的时候,90%的第一个程序都是WordCount,所以在这里分享一下我的第二个MapReduce程序.对于学习编程语言的人来说,有时候代码是最好的沟通方式之一 ...

  9. EasyUI 树菜单

    EasyUI 树菜单 通过ssm框架项目实现EasyUI 的树菜单的单选,复选,异步加载树,同步加载树和树权限控制等功能. 本章知识点 效果图: 需求:通过SSM框架,实现EasyUI 树菜单的单选, ...

  10. 快速拥有各种数据访问SqlHelper

    常加班食不按时,偶得清闲嘴溃疡. 美食一顿成泡汤,自此自认忙命人. 这就是此情此景的我,回来聊代码. 列举ADO.NET中的五个主要对象,并简单描述? 答:Connection连接对象,Command ...