剑指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 ...
随机推荐
- SQL Server 2008对日期时间类型的改进
微软在备受多年的争议后,终于对日期时间数据类型开刀了,在新版的SQL Server 2008中一口气增加了4种新的日期时间数据类型,包括: Date:一个纯的日期数据类型. Time:一个纯的时间数据 ...
- Struts2开发文档
struts2配置 struts2核心配置文件约束 <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts ...
- openstack学习心得:keystone 架构、概念、访问流程
1.keystone 介绍及其组成 OpenStack Identity 服务提供了一个单一的功能集合,包括管理认证,授权和服务目录. Identity 服务通常作为和用户第一个交互的服务.一旦认证成 ...
- 如何在ASP.NET Core Web API测试中使用Postman
使用Postman进行手动测试 如果您是开发人员,测试人员或管理人员,则在构建和使用应用程序时,有时了解各种API方法可能是一个挑战. 使用带有.NET Core的Postman为您的Web API生 ...
- flex词法解析
例子1.从标准输入的字数.单词.行数统计 %{ #include <string.h> int chars = 0; int lines = 0; int words = 0; %} %% ...
- MySQL子查询优化实例
优化:子查询改写成关联查询 线上遇到问题,查询较慢,如为对应SQL的查询执行计划: localhost.\G . row *************************** id: select_ ...
- pandas选择数据-【老鱼学pandas】
选择列 根据列名来选择某列的数据 import pandas as pd import numpy as np dates = pd.date_range("2017-01-08" ...
- .NET之RabbitMQ学习笔记(一)-应用场景
使用场景 1.异步处理 用户注册后,需要发注册邮件和注册短信,传统的做法有两种1.串行的方式;2.并行的方式 (1)串行处理方式:注册信息写数据库-发送注册邮件-发送注册短信,等上述三个操作都执行完成 ...
- 【Java入门提高篇】Day3 抽象类与接口的比较
抽象类跟接口都讲完了,现在来做一个比较. 其实说实话,没有多大的可比较性,它们是完全不同的两个东西,它们的抽象不在同一个层级上.但是为了让大家更好的理解,还是做一个比较吧,毕竟它们都很抽象(233). ...
- Caddy服务器搭建和实现文件共享
1:Caddy介绍 作为新兴 Web 服务器,Caddy 提供了很多简单易用的功能而没有历史的包袱,其默认支持并且能帮你自动配置 HTTP/2.HTTPS,对于 IPV6.WebSockets 都有很 ...