《劍指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多行,我表示受到了驚嚇,有機會再說吧

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM