LeetCode111——二叉树最小深度c++多方法详解

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

既然提到了深度的问题那就不得不先提到最大深度的获取,这道题在leetcode上面也有,不过大家就按字面意思理解很清晰的明白它无非就是让你求一个二叉树最大深度。

首先,先给大家排一个坑。这个坑就属于很典型的自己编译和OJ的差异——也就是说本地调试无误,但是上机超时的问题。

//这一种方法在OJ上不存在超时
int maxDepth(TreeNode *p)
{
    if(!p)
        return 0;
    int lengthl = maxDepth(p->left)+1;
    int lengthr = maxDepth(p->right)+1;
    
    return lengthl>lengthr?lengthl:lengthr;
}

//下面这种看似无敌简洁逻辑的写法,上了OJ就GG啦
int maxDepth(TreeNode *p)
{
    if(!p)
        return 0;

    return maxDepth(p->left)>maxDepth(p->right)?:maxDepth(p->left)+1:maxDepth(p->right)+1;
}

对于代码量稍低的同志,要是问大家哪种方法更好,大家肯定毫不犹豫的说下面那种 ,看起来确实高大上那么一点、且代码量要短。但是大家忽略了一个问题,下面这种方法的return表达式中实际上相同的式子并列的递归了两次,那么这种写法超时的原因从直接层面上来说是time*2导致的超时。更深层次而言,如果在函数体中改变了指针的指向,这种方法会导致错误产生,即前后两个同样的表达式内参数的指向并不相同。

排掉了最大深度的坑,我们看回到原题,也就是我们要求的最小深度。在理解了最大深度的递归求解方法之后,我们自然而然的想到将表达式的return值改为

return lengthl>lengthr?lengthr:lengthl;

也就是去找那个小的值,但是大家考虑一种情况,也就是当你遍历到一个节点,这个节点的度为1.这时按照我们已有的写法,当判断到该节点空的那个孩子时,我们的递归就会结束并开始返回。但实际上度为1的节点我们是要沿着它非空的孩子继续向下找,直到找到最后的叶子节点,这才能求出一个正确的深度值。

那么,针对这个条件的改变,我们需要加入一些判定,下面给出完整代码

class Solution {
public:
    int minDepth(TreeNode* root) {
        
        if(!root)
            return 0;
        
        if(!root->left&&!root->right)
            return 1;
        
        else if((!root->left&&root->right)||(root->left&&!root->right))
        {
            root = root->left?root->left:root->right;
            return minDepth(root)+1;
        }
        
            int lengthl = minDepth(root->left)+1;
            int lengthr = minDepth(root->right)+1;
            
            return lengthl>lengthr?lengthr:lengthl;
        
            
    }
};

碰到度为1的节点,我们人为地让他沿着非空的孩子继续向下走即可~ 

众所周知,二叉树是可以使用队列进行保存并进行广度遍历的(说直白就是可以实现一层一层的遍历),那么我们使用queue的方式实现这道题


class Solution {
    private:
        queue a;
    
public:
    int minDepth(TreeNode* root) {
        
        if(!root)
            return 0;
        
        int count = 1;
        
        a.push(root);
        
        while(!a.empty())
        {
            int size = a.size();
            
            for(int i = 0;iright)
                {
                    a.push(b->right);
                }
                if(b->left)
                {
                    a.push(b->left);
                }
                if(!b->right&&!b->left)
                {
                    return count;
                }
            }
             count++;
          
        }
            return count;
    }
};

 这里有一个小坑,在for循环的时候,大家一定注意不要把a.size()作为上界,当时没怎么留神这里,想当然的这么写了却发现怎么都不对。原因很简单,每次pop()或者Push()后,a.size()都发生了变化,即如果使用size()作为上界那么每次for循环在执行时候的上界是在持续浮动的。即 i和i+1对应的上界是不同的。

2333,有点无语,但是小坑一定要注意

 

 

 

你可能感兴趣的:(Leetcode,树,DataStructure)