• 《剑指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多行,我表示受到了惊吓,有机会再说吧

  • 相关阅读:
    如何获得浏览器localStorage的剩余容量
    按Enter键后Form表单自动提交的问题
    IE10 11的css hack
    text-transform设置单词首字母大写
    Jade模板引擎(一)之Attributes
    sql server之ROW_NUMBER() OVER()取每组的第N行数据
    CSS3之让背景图片全部显示
    摆脱npm的网络问题: 淘宝npm镜像
    MaskedTextBox的聚焦和光标位置
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/xuanxufeng/p/6857695.html
Copyright © 2020-2023  润新知