104. 二叉树的最大深度(三种解法) 110. 平衡二叉树(两种解法) 111. 二叉树的最小深度(两种解法)

104. 二叉树的最大深度

题目:

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

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

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

解法1:递归

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (NULL == root)
            return 0;
        int leftDep = maxDepth(root->left) + 1;
        int rightDep = maxDepth(root->right) + 1;
        return leftDep > rightDep ? leftDep : rightDep;
    }
};

         在递归中,如果不想用到临时变量,可以选择用max()方法。具体程序可参考如下:

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(root == NULL) {
            return 0;
        }

        return max(maxDepth(root->left), maxDepth(root->right)) + 1;
    }
};

        有时候调用max()方法,程序无法识别,就会想到宏,具体程序可参考如下:

#define MAX(x,y) ((x)>(y)?(x):(y))      //莫忘最外层括号
class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (NULL == root)
            return 0;

        return MAX(maxDepth(root->left), maxDepth(root->right)) + 1;
    }
};

       但是,这种实现会超出时间限制。为什么呢?

       不由得想说明是宏?是在预编译的时候进行文本替换,那么在MAX的地方,运行时会调用maxDepth()三次:((x)>(y)?(x):(y))。所以当树比较深的时候会超时。因此,宏不要用在递归函数上。

解法2:用从上到下打印二叉树的思想,深度即层数

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(nullptr == root)
            return 0;

        queue<TreeNode*> que;
        que.push(root);
        int depth = 0;
        while(!que.empty()){
            depth++;
            int len =que.size();
            while (len--) {
                TreeNode* node=que.front();
                que.pop();           
                if(node->left!=nullptr)
                    que.push(node->left);
                if(node->right!=nullptr)
                    que.push(node->right);
            }
        }

        return depth;
    }
};

解法3:用一个全局变量记录层数,每层判断

class Solution {
public:
    void cntLevel(TreeNode* root, int curLevel, int& depth) {
        if (NULL == root)
            return;
        if (curLevel > depth)
            depth = curLevel;

        cntLevel(root->left, curLevel + 1, depth);
        cntLevel(root->right, curLevel + 1, depth);
    }
    int maxDepth(TreeNode* root) {
        int depth = 0;
        cntLevel(root, 1, depth);

        return depth;
    }
};

        这种方法,没有递归调用,也不用操作具体的节点,效率较高。

110. 平衡二叉树

题目:

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

 解法1:计算数的深度,由上至下

class Solution {
private:
    int treeDepth(TreeNode* root) {
        if (NULL == root)
            return 0;

        return max(treeDepth(root->left), treeDepth(root->right)) + 1;
    }
public:
    bool isBalanced(TreeNode* root) {
        if (NULL == root) 
            return true;

        return abs(treeDepth(root->left) - treeDepth(root->right)) <= 1
                && isBalanced(root->left)
                && isBalanced(root->right);
    }
};

解法2:由下至上,子树不平衡即不平衡

class Solution {
private:
    bool isBalance(TreeNode* root, int& deep) {
        if (NULL == root) {
            deep = 0;
            return true;
        }

        int leftLen, rightLen;
        if (isBalance(root->left, leftLen)
            && isBalance(root->right, rightLen)
            && abs(leftLen - rightLen) <= 1) {
                deep = max(leftLen, rightLen) + 1;
                return true;
            }

        return false;
    }
public:
    bool isBalanced(TreeNode* root) {
        if (NULL == root)
            return true;
        
        int deep = 0;
        return isBalance(root, deep);
    }
};

        这种思路是在计算长度的时候,及时判断是否为平衡。此思路还有另一种实现,具体如下程序:

class Solution {
private:
    int depth(TreeNode* root, bool& flag) {
        if (NULL == root) {
            flag = true;
            return 0;
        }

        bool left, right;
        int leftLen = depth(root->left, left);
        int rightLen = depth(root->right, right);
        if (left && right && abs(leftLen - rightLen) <= 1) {
                flag = true;
                return max(leftLen, rightLen) + 1;
            }

        flag = false;
        return -1;    //无效,无须计算
    }
public:
    bool isBalanced(TreeNode* root) {
        if (NULL == root)
            return true;
        
        bool flag;
        depth(root, flag);

        return flag;
    }
};

111. 二叉树的最小深度

题目:

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

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

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

题目要点:

最小深度定义为到最近叶子节点的深度,当左右子树都为空,最小深度才为1。

解法1:分类讨论子节点情况

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (NULL == root)
            return 0;
        
        int left = minDepth(root->left);
        int right = minDepth(root->right);

        if (0 == left && 0 == right)                //1为根节点所在的深度
            return 1;
        if (0 == left || 0 == right)
            return 0 == left ? right + 1 : left + 1;
        return min(left, right) + 1;
    }
};

      这种解法根据返回情况写的很详细直白,理解后返回判断可以进一步简写如下:

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (NULL == root)
            return 0;
        
        int left = minDepth(root->left);
        int right = minDepth(root->right);

        if (0 == left || 0 == right)
            return max(left, right) + 1;  //1为根节点所在的深度
        return min(left, right) + 1;
    }
};

        甚至可以直接简写为一个三元式,具体程序如下:

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (NULL == root)
            return 0;

        int left = minDepth(root->left);
        int right = minDepth(root->right);

        return (left && right) ? 1 + min(left, right) : 1 + left + right;
    }
};

        其中(left && right)不成立时,说明左右子节点至少有一个为空,即left和right至少有一个为0,  1+left+right数值上等于要求的数,没有别的特殊意义。

        有很多同学第一次写,很容易写成如下程序(本题的错误解法,通不过的测试例如[1,2]),这就是没有好好理解最小深度的定义。

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

解法2:用从上至下打印二叉树的队列思路,遇到叶子节点短路处理

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(NULL == root)
            return 0;

        queue<TreeNode*> que;
        que.push(root);
        int depth = 0;
        while(!que.empty()){
            int len = que.size();
            while (len--) {
                TreeNode* node = que.front();
                que.pop();
                if(NULL == node->left && NULL == node->right)
                    return depth + 1;
                if(node->left)
                    que.push(node->left);
                if(node->right)
                    que.push(node->right);
            }
            depth++;
        }

        return depth;        
    }
};

         这种思路,处理到第一个叶子节点就结束了,效率较好。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值