111. 二叉树的最小深度

111. 二叉树的最小深度

求最小深度/根节点到最近叶子节点的最短路径上的节点数量;

递归解法

递归解1(错解)

尝试考虑:

在求解的过程中下落到某个树(t)

  • 如果(t)为空, 那么它的最小深度为0;

  • 如果(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;
    }
};

这显然是错误的, 例如:

输入:
[1,2]
输出
1
预期结果
2

PS: 实际上上面的三条规则是冗余的, 可以化简为:

  • 如果(t)为空, 那么它的最小深度为0;

  • 否则它的最小深度等于(1 + min(h_l, h_r));

递归解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%的用户
原文地址:https://www.cnblogs.com/owxc/p/12465961.html