劍指Offer-40-二叉樹的深度

Special__Yang發表於2018-08-13

題目

輸入一棵二叉樹,求該樹的深度。從根結點到葉結點依次經過的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度為樹的深度。

解析

預備知識

樹的深度為根節點到葉子節點中所有的路徑長度最長的值。如圖:
這裡寫圖片描述
圖中根節點到葉子節點最長的路徑為:1->3->5->6,所以深度為4.

思路一

我們很容易想到一個樹深度為左子樹和右子樹深度的最大值 + 1。所以問題規模轉變為求左子樹和右子樹的深度,問題形式不變,規模變小,典型的遞迴問題。所以很容易寫出如下精簡的程式碼:

    public static int TreeDepth4(TreeNode root) {
        if(root == null) {
            return 0;
        }
        int left = TreeDepth4(root.left);
        int right = TreeDepth4(root.right);
        return Math.max(left, right) + 1;
    }

思路二

我們都知道遞迴在問題規模很大的時候容易出現棧溢位,所以我們嘗試換種思路來避免遞迴。
在樹的遍歷中,實現簡單而不是遞迴的寫法就屬層序遍歷了。

層序遍歷:顧名思義,就是從根節點一層一層的遍歷整棵樹。

我們可以按層來處理,每遍歷一層,深度加一,直到遍歷完整棵樹,即可得到層數(即深度)。層序遍歷也就是BFS非常適合用先進先出的佇列來充當容器,深度初始為0,根節點先入隊,然後處理第一層,深度加1,並把第二層的節點加入;之後繼續處理第二層,深度加1,獲取當前佇列的大小,此時佇列的大小即為當前層節點總數size,依次從佇列中取出大小為size的節點,期間並把這些節點的孩子節點加入(即下一層的);重複以上步驟,直到佇列為空,表明遍歷到最底層。

    public static int TreeDepth(TreeNode root) {
        if(root == null) {
            return 0;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        int depth = 0;
        while(!queue.isEmpty()) {
            int currentLayerSize = queue.size();
            depth++;
            for(int i = 0; i < currentLayerSize; i++) {
                TreeNode node = queue.poll();
                if(node.left != null) {
                    queue.offer(node.left);
                }
                if(node.right != null) {
                    queue.offer(node.right);
                }
            }
        }
        return depth;
    }

思路三

思路三跟思路二一樣,只不過按層處理的策略不同。
思路二是通過每次把當前層的節點彈出來確保最外層每次訪問都是樹的每一層。
而思路三是借用2個指標last,nLast。其中last指向當前層的最後一個節點,nLast指向下一層的最後一個節點。
1. 初始last指向根節點,root進棧。
2. 開始迴圈體,判斷棧是否為空,不為空,則彈出節點node,繼續步驟3;否則步驟5
3. 判斷node的左右孩子是否不為空,若不為空,則入隊,並更新nLast指向孩子。
4. 判斷node是否等於last,若是,則表明下一次該訪問下一層了,所以深度加1,並把last更新為nLast
5. 結束迴圈,返回深度

    public static int TreeDepth3(TreeNode root) {
        if(root == null) {
            return 0;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        int depth = 0;
        TreeNode last = root, nLast = null;
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if(node.left != null) {
                queue.offer(node.left);
                nLast = node.left;
            }
            if(node.right != null) {
                queue.offer(node.right);
                nLast = node.right;
            }
            if(node == last) {
                depth++;
                last = nLast;
            }
        }
        return depth;
    }

總結

有序陣列的查詢首選二分查詢。

相關文章