「leetcode」111.二叉樹的最小深度

程式碼隨想錄發表於2020-10-08

111.二叉樹的最小深度

給定一個二叉樹,找出其最小深度。

最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。

說明: 葉子節點是指沒有子節點的節點。

示例:

給定二叉樹 [3,9,20,null,null,15,7],

 

 

返回它的最小深度 2.

思路

看完了這篇二叉樹:看看這些樹的最大深度,再來看看如何求最小深度。

直覺上好像和求最大深度差不多,其實還是差不少的。

遍歷順序上依然是後序遍歷(因為要比較遞迴返回之後的結果),但在處理中間節點的邏輯上,最大深度很容易理解,最小深度可有一個誤區,如圖:

 

 

這就重新審題了,題目中說的是:「最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。」,注意是「葉子節點」

什麼是葉子節點,左右孩子都為空的節點才是葉子節點!

遞迴法

來來來,一起遞迴三部曲:

  1. 確定遞迴函式的引數和返回值

引數為要傳入的二叉樹根節點,返回的是int型別的深度。

程式碼如下:

int getDepth(TreeNode* node)
  1. 確定終止條件

終止條件也是遇到空節點返回0,表示當前節點的高度為0。

程式碼如下:

if (node == NULL) return 0;
  1. 確定單層遞迴的邏輯

這塊和求最大深度可就不一樣了,一些同學可能會寫如下程式碼:

int leftDepth = getDepth(node->left);
int rightDepth = getDepth(node->right);
int result = 1 + min(leftDepth, rightDepth);
return result;

這個程式碼就犯了此圖中的誤區:

 

 

如果這麼求的話,沒有左孩子的分支會算為最短深度。

所以,如果左子樹為空,右子樹不為空,說明最小深度是 1 + 右子樹的深度。

反之,右子樹為空,左子樹不為空,最小深度是 1 + 左子樹的深度。最後如果左右子樹都不為空,返回左右子樹深度最小值 + 1 。

程式碼如下:

int leftDepth = getDepth(node->left);    // 左
int rightDepth = getDepth(node->right);  // 右
                                         // 中
// 當一個左子樹為空,右不為空,這時並不是最低點
if (node->left == NULL && node->right != NULL) { 
    return 1 + rightDepth;
}   
// 當一個右子樹為空,左不為空,這時並不是最低點
if (node->left != NULL && node->right == NULL) { 
    return 1 + leftDepth;
}
int result = 1 + min(leftDepth, rightDepth);  
return result;

遍歷的順序為後序(左右中),可以看出:「求二叉樹的最小深度和求二叉樹的最大深度的差別主要在於處理左右孩子不為空的邏輯。」

整體遞迴程式碼如下:

class Solution {
public:
    int getDepth(TreeNode* node) {
        if (node == NULL) return 0;
        int leftDepth = getDepth(node->left);    // 左
        int rightDepth = getDepth(node->right);  // 右
                                                 // 中
        // 當一個左子樹為空,右不為空,這時並不是最低點
        if (node->left == NULL && node->right != NULL) { 
            return 1 + rightDepth;
        }   
        // 當一個右子樹為空,左不為空,這時並不是最低點
        if (node->left != NULL && node->right == NULL) { 
            return 1 + leftDepth;
        }
        int result = 1 + min(leftDepth, rightDepth); 
        return result;
    }

    int minDepth(TreeNode* root) {
        return getDepth(root);
    }
};

精簡之後程式碼如下:

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        if (root->left == NULL && root->right != NULL) {
            return 1 + minDepth(root->right);
        }
        if (root->left != NULL && root->right == NULL) {
            return 1 + minDepth(root->left);
        }
        return 1 + min(minDepth(root->left), minDepth(root->right));
    }
};

「精簡之後的程式碼根本看不出是哪種遍歷方式,所以依然還要強調一波:如果對二叉樹的操作還不熟練,儘量不要直接照著精簡程式碼來學。」

迭代法

相對於二叉樹:看看這些樹的最大深度,本題還可以使用層序遍歷的方式來解決,思路是一樣的。

如果對層序遍歷還不清楚的話,可以看這篇:二叉樹:層序遍歷登場!

「需要注意的是,只有當左右孩子都為空的時候,才說明遍歷的最低點了。如果其中一個孩子為空則不是最低點」

程式碼如下:

class Solution {
public:

    int minDepth(TreeNode* root) {
        if (root == NULL) return 0;
        int depth = 0;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            int size = que.size(); 
            depth++; // 記錄最小深度
            int flag = 0;
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
                if (!node->left && !node->right) { // 當左右孩子都為空的時候,說明是最低點的一層了,退出
                    flag = 1;
                    break;
                }
            }
            if (flag == 1) break;
        }
        return depth;
    }
};

 

本文:https://github.com/youngyangyang04/leetcode-master​已經收錄,裡面還有leetcode刷題攻略、各個型別經典題目刷題順序、思維導圖,可以fork到自己倉庫,有空看一看一定會有所收穫,如果對你有幫助也給一個star支援一下吧!

我的B站(裡面有我講解的演算法視訊以及程式設計相關知識)https://space.bilibili.com/525438321

我是程式設計師Carl,哈工大師兄,先後在騰訊和百度從事技術研發多年,利用工作之餘重刷leetcode,更多     精彩演算法文章盡在:   程式碼隨想錄,關注後,回覆「Java」「C++」「python」「簡歷模板」等等,有我整理多年的學習資料,可以加我    微信,備註「個人簡介」+「組隊刷題」,拉你進入刷題群(無任何廣告,純個人分享),每天一道經典題目分析,我選的每一道題目都不是孤立的,而是由淺入深一脈相承的,如果跟住節奏每篇連續著看,定會融會貫通。

相關文章