111. 二叉樹的最小深度

111. 二叉樹的最小深度

求最小深度/根節點到最近葉子節點的最短路徑上的節點數量;c++

遞歸解法

遞歸解1(錯解)

嘗試考慮:函數

在求解的過程當中下落到某個樹\(t\)spa

  • 若是\(t\)爲空, 那麼它的最小深度爲0;code

  • 若是\(t\)的左子樹和右子樹都非空, 那麼它的最小深度等於\(1 + min(h_l, h_r)\);
  • 若是\(t\)的左子樹爲空或右子樹爲空, 那麼它的最小深度等於1;遞歸

能夠寫出以下代碼內存

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

這顯然是錯誤的, 例如:leetcode

輸入:
[1,2]
輸出
1
預期結果
2

PS: 實際上上面的三條規則是冗餘的, 能夠化簡爲:get

  • 若是\(t\)爲空, 那麼它的最小深度爲0;io

  • 不然它的最小深度等於\(1 + min(h_l, h_r)\);class

遞歸解2

能夠讓被拋給遞歸函數的t確保爲非空;

  • 若是\(t\)的左右子樹都非空, 則\(minDepth = 1 + min(h_l, h_r)\);
  • 再若是\(t\)的左右子樹都爲空, 則\(minDepth = 1\);
  • 最後對於左右子樹一個爲空, \(minDepth = 1 + minDepth_{非空子樹}\);
class Solution {
public:
    int helper(TreeNode* t) {
        if(t->left!=nullptr && t->right!=nullptr) return 1 + min(minDepth(t->left), minDepth(t->right));
        if(t->left==nullptr && t->right==nullptr) return 1;
        return 1 + minDepth((t->left!=nullptr) ? t->left : t->right);
    }
    int minDepth(TreeNode* root) {
        if(root==nullptr) return 0;
        return helper(root);
    }
};
執行用時 :20 ms, 在全部 C++ 提交中擊敗了35.52%的用戶
內存消耗 :21.6 MB, 在全部 C++ 提交中擊敗了5.10%的用戶

遞歸解3

官方題解

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(root==nullptr) return 0;
        if(root->left==nullptr && root->right==nullptr) return 1;
        int minD = INT_MAX;
        if(root->left!=nullptr) minD = min(minD, minDepth(root->left));
        if(root->right!=nullptr) minD = min(minD, minDepth(root->right));
        return 1+minD;
    }
};
執行用時 :20 ms, 在全部 C++ 提交中擊敗了35.52%的用戶
內存消耗 :22.1 MB, 在全部 C++ 提交中擊敗了5.10%的用戶

注:

  • 以上題解都注意區分了根節點爲空的狀況;

迭代解

求一棵樹的最大深度過程當中, 咱們記得層序遍歷的時候, 能夠得到當前遍歷的深度, 因此直接能夠得出最大深度;

而在層序遍歷時, 也能夠知道當前這個節點是否是葉子節點;

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(root==nullptr) return 0;
        int minD = INT_MAX;
        deque<TreeNode*> q;
        q.push_back(root);
        int curDepth = 1;
        while(!q.empty()) {
            int n = q.size();
            for(int i=0; i<n; ++i) {
                TreeNode* t = q.front();
                q.pop_front();
                if(t->left==nullptr && t->right==nullptr)
                    minD = min(minD, curDepth);
                if(t->left!=nullptr) q.push_back(t->left);
                if(t->right!=nullptr) q.push_back(t->right);
            }
            ++curDepth;
        }
        return minD;
    }
};

效率都差很少

執行用時 :20 ms, 在全部 C++ 提交中擊敗了35.52%的用戶
內存消耗 :21.3 MB, 在全部 C++ 提交中擊敗了5.10%的用戶

上面的方法還有一處愚蠢:

  • BFS層序遍歷過程當中深度是單調增的, 因此找到的第一個葉子節點深度就是最終要求的minDepth;
class Solution {
public:
    int minDepth(TreeNode* root) {
        if(root==nullptr) return 0;
        int minD = INT_MAX;
        deque<TreeNode*> q;
        q.push_back(root);
        int curDepth = 1;
        while(!q.empty()) {
            int n = q.size();
            for(int i=0; i<n; ++i) {
                TreeNode* t = q.front();
                q.pop_front();
                if(t->left==nullptr && t->right==nullptr) {
                    minD = min(minD, curDepth);
                    break;  /// #找到第一個葉子即完成
                }
                if(t->left!=nullptr) q.push_back(t->left);
                if(t->right!=nullptr) q.push_back(t->right);
            }
            ++curDepth;
        }
        return minD;
    }
};

快了很多

執行用時 :12 ms, 在全部 C++ 提交中擊敗了85.32%的用戶
內存消耗 :21.4 MB, 在全部 C++ 提交中擊敗了5.10%的用戶
相關文章
相關標籤/搜索