《剑指offer》面试题39 二叉树的深度(java)

摘要:

今天翻到了《剑指offer》面试题39,题目二中的解法二是在函数的参数列表中通过指针的方式进行传值,而java是没有指针的,所以函数要进行改造。然而我翻了下别人的java版本(我就想看看有什么高大上的改造,毕竟要传递多个参数,是不是会涉及到那么一点点设计模式呢?),简直不能忍了,我只能用一句话形容:“一本正经的胡说八道”,不过我就是喜欢看你胡说八道还迷之自信的样子。

下面吐槽一下这个版本的java代码:

 1 //高效率的判断是否是一棵平衡二叉树
 2     public boolean isBalanced2(BinaryTreeNode root){
 3         int depth = 0;
 4         return isBalanced2(root,depth);
 5     }
 6     public boolean isBalanced2(BinaryTreeNode root,int depth){
 7         if(root == null){
 8             depth = 0;
 9             return true;
10         }
11         int left = 0,right = 0;
12         if(isBalanced2(root.leftNode,left) && isBalanced2(root.rightNode,right)){
13             int diff = left-right;
14             if(diff <= 1 && diff >= -1){
15                 depth = 1+(left > right?left : right);
16                 return true;
17             }
18         }
19         return false;
20     }  

这个文章的原始链接我就不发了,保留一点人品。关键是特么CSDN竟然把他作为百度搜索第一条置顶了,可见人气是最高的,看看作者发帖历史(好像还有那么一点小屌),我TM差点就信了。这个哥们连函数参数的复制传值都不懂啊!怎么学的编程,还发帖误导广大小学生,简直不能忍。我看也不用参考别人的代码了,自己写一个吧。

原题一:输入一颗二叉树的根结点,求该树的深度。从根结点到叶结点依次经过的结点(含根,叶子结点)形成一条路径,最长路径的长度为树的深度。

输入样例:

1

2     3

4   5     6

7

源代码:

class BinaryTreeNode{

    public int data;
    public BinaryTreeNode left;
    public BinaryTreeNode right;

    public BinaryTreeNode(){
        data = 0;
        left = null;
        right = null;
    }
}
public class Question_39 {
    //----递归求二叉树深度----
    public static int treeDepth(BinaryTreeNode root){
        if(root == null){
            return 0;
        }
        int left = treeDepth(root.left);
        int right = treeDepth(root.right);

        return (left>right)?(left+1):(right+1);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BinaryTreeNode node1 = new BinaryTreeNode();
        BinaryTreeNode node2 = new BinaryTreeNode();
        BinaryTreeNode node3 = new BinaryTreeNode();
        BinaryTreeNode node4 = new BinaryTreeNode();
        BinaryTreeNode node5 = new BinaryTreeNode();
        BinaryTreeNode node6 = new BinaryTreeNode();
        BinaryTreeNode node7 = new BinaryTreeNode();

        node1.data = 1;
        node2.data = 2;
        node3.data = 3;
        node4.data = 4;
        node5.data = 5;
        node6.data = 6;
        node7.data = 7;

        node1.left = node2;
        node1.right = node3;
        node2.left = node4;
        node2.right = node5;
        node5.left = node7;
        node3.right = node6;

        System.out.println("递归求二叉树深度: "+treeDepth(node1));

    }
}

这道题比较简单,没什么好说的。

题目二:输入一颗二叉树的根结点,判断该树是不是平衡二叉树。如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一颗平衡二叉树。

方法一:需要重复遍历多次的解法,简单但不足以打动面试官

 1 public static boolean isBalanced_1(BinaryTreeNode root){
 2         if(root==null){
 3             return true;
 4         }
 5         int left = treeDepth(root.left);
 6         int right = treeDepth(root.right);
 7         int diff = left - right;
 8         if(diff>1||diff<-1){
 9             return false;
10         }
11         return isBalanced_1(root.left)&&isBalanced_1(root.right);
12     }

该方法简洁,但是一个结点会被重复遍历多次,时间效率不高。

方法二:每个结点只遍历一次,面试官喜欢

 1 class Tuple{
 2     private boolean isBalanced;
 3     private int depth;
 4
 5     public Tuple(){}
 6     public Tuple(boolean isBalanced, int depth) {
 7         super();
 8         this.isBalanced = isBalanced;
 9         this.depth = depth;
10     }
11     //-----isBalanced,Getters and Setters----
12     public boolean getIsBalanced() {
13         return isBalanced;
14     }
15     public void setIsBalanced(boolean isBalanced) {
16         this.isBalanced = isBalanced;
17     }
18     //-----depth,Getters and Setters----
19     public int getDepth() {
20         return depth;
21     }
22     public void setDepth(int depth) {
23         this.depth = depth;
24     }
25
26
27 }
28 //----判断平衡二叉树,每个结点只遍历一次----
29     private static Tuple isBalanced(BinaryTreeNode root){
30         if(root==null){
31             Tuple tuple = new Tuple();
32             tuple.setIsBalanced(true);
33             tuple.setDepth(0);
34             return tuple;
35         }
36         Tuple left =  isBalanced(root.left);
37         Tuple right = isBalanced(root.right);
38
39         if(left.getIsBalanced()&&right.getIsBalanced()){
40             int diff = left.getDepth()-right.getDepth();
41             if(diff<=1&&diff>=-1){
42                 return new Tuple(true,(left.getDepth()>right.getDepth()?left.getDepth():right.getDepth()) + 1 );
43             }
44         }
45         return  new Tuple(false,-1);
46     }
47     public static boolean isBalancedBinaryTree(BinaryTreeNode root){
48         Tuple tuple =  isBalanced(root);
49         return tuple.getIsBalanced();
50     }

在上面的代码中,我们使用后序遍历的方式遍历整颗二叉树。在遍历某结点的左右子结点之后,我们可以根据它的左右子结点的深度判断它是不是平衡的,并得到当前结点的深度。当遍历到根结点的时候,也就判断了整颗二叉树是不是平衡二叉树。由于要传递两个参数,一般的使用返回值的方法是行不通的,而且Java并不存在指针和简单数据类型的引用传值。一般的高级语言(如Python)会有元组这么一个概念(Java没有那就自己定义一个),既然只能返回一个值,那就返回一个复合类型的,函数改造完成~

我想说的是,每个入了门的程序员都知道参数是复制传值,在C/C++中只能用指针和引用的方式从参数列表中传递或获取值,在Java中,除了基本数据类型和String类型外,也是引用传值。但是基本数据类型传进函数体你改动了有什么意义?你只是改动了一个副本。为了呵护祖国下一代程序员的健康成长,老夫专门抽时间写了一篇博客(抠鼻),打击不良之风~  本来想和平衡二叉树结合一起写一篇文章,但是平衡二叉树TMD代码一下子要写500多行,我表示受到了惊吓,有机会再说吧

时间: 2024-08-03 19:59:41

《剑指offer》面试题39 二叉树的深度(java)的相关文章

剑指Offer面试题39(Java版):二叉树的深度

题目:输入一棵二叉树的根节点,求该数的深度.从根节点到叶结点依次进过的结点(含根,叶结点)形成树的一条路径,最长路径的长度为树的深度. 例如,如下图的二叉树的深度为4,因为它从根节点到叶结点的最长的路径包含4个结点(从根结点1开始,经过2和结点5,最终到达叶结点7) 我们可以从另一种角度来理解树的深度.如果一棵树只有一个结点,它的深度为1,如果根节点只有左子树而没有右子树,那么树的深度应该是其左子树的深度+1.同样如果根节点只有右子树而没有左子树,那么树的深度应该是其右子树+1.如果既有左子树又

二叉树层次遍历(剑指Offer面试题32:从上到下打印二叉树)

图1所示为二叉树的层次遍历,即按照箭头所指方向,按照1.2.3的层次顺序,对二叉树每个节点进行访问 (此图反映的是自左至右的层次遍历,自右至左的方式类似). 要进行层次遍历,需要建立一个队列.先将二叉树头节点入队列,然后出队列,访问该节点, 如果它有左子树,则将左子树的根结点入队:如果它有右子树,则将右子树的根结点入队.然后出队列,对出队节点访问, 如此反复直到队列为空为止. 1 import java.util.*; 2 class TreeNode 3 { 4 int val; 5 Tree

[ 剑指offer ] 面试题8:二叉树的下一个节点

题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 解题思路 1.找到所有的可能情况并归纳,写的代码需要把这些情况都覆盖到. 2.具体情况详见书本# -*- coding:utf-8 -*- # class TreeLinkNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None # self

剑指Offer对答如流系列 - 序列化二叉树

面试题37:序列化二叉树 题目描述 请实现两个函数,分别用来序列化和反序列化二叉树. 树的结构定义如下: public class Node { int val = 0; Node left = null; Node right = null; public Node(int val) { this.val = val; } } 问题分析 一般情况下,需要采用前/后序遍历和中序遍历才能确定一个二叉树,具体的内容我们之前探讨过 剑指Offer对答如流系列 - 重建二叉树 但是采用这种方式进行序列化

【剑指Offer面试题】二维数组中的查找

下决心AC所有剑指offer面试题. 九度OJ面试题地址:http://ac.jobdu.com/hhtproblems.php 书籍:何海涛--<剑指Offer:名企面试官精讲典型编程题> 对于面试题,面试官往往更希望我们能提出优化方法,这样更能体现我们的思维能力以及传说中的"内功".所以做剑指offer要着重训练这方面,多总结多细究,总是有好处的.加油~ 二维数组中的查找 时间限制:1 秒内存限制:32 兆 特殊判题:否提交:19005解决:3642 题目描述: 在一个

【剑指Offer面试题】九度OJ1384:二维数组中的查找

下决心AC全部剑指offer面试题. 九度OJ面试题地址:http://ac.jobdu.com/hhtproblems.php 书籍:何海涛--<剑指Offer:名企面试官精讲典型编程题> 对于面试题,面试官往往更希望我们能提出优化方法,这样更能体现我们的思维能力以及传说中的"内功".所以做剑指offer要着重训练这方面,多总结多细究,总是有优点的.加油~ 题目链接地址: http://ac.jobdu.com/problem.php?pid=1384 二维数组中的查找

【剑指Offer面试题】 九度OJ1516:调整数组顺序使奇数位于偶数前面

题目链接地址: http://ac.jobdu.com/problem.php?pid=1516 题目1516:调整数组顺序使奇数位于偶数前面 时间限制:1 秒内存限制:128 兆特殊判题:否提交:2858解决:924 题目描写叙述: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得全部的奇数位于数组的前半部分,全部的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 输入: 每一个输入文件包括一组測试案例. 对于每一个測试案例.第一行输入一个n,代表该数组

【剑指Offer面试题】 九度OJ1386:旋转数组的最小数字

题目链接地址: http://ac.jobdu.com/problem.php?pid=1386 题目1386:旋转数组的最小数字 时间限制:1 秒内存限制:32 兆特殊判题:否提交:6914解决:1534 题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入的第一行为

剑指Offer 面试题36:数组中的逆序对及其变形(Leetcode 315. Count of Smaller Numbers After Self)题解

剑指Offer 面试题36:数组中的逆序对 题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 例如, 在数组{7,5,6,4}中,一共存在5个逆序对,分别是(7,6),(7,5),(7,4),(6,4)和(5,4),输出5. 提交网址: http://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5?tpId=13&tqId=11188 或 htt

剑指Offer:对称的二叉树【28】

剑指Offer:对称的二叉树[28] 题目描述 请实现一个函数,用来判断一颗二叉树是不是对称的.注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的. 题目分析 Java题解 /* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */ public class Solution {