算法训练 day16 | 104.二叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数

104.二叉树的最大深度

题目链接:二叉树的最大深度

视频讲解:二叉树的深度和高度有啥区别?

        对于此题首先得弄清二叉树的深度和高度的区别,才能弄清解决这道题的本质。深度是任意一节点到根节点的距离,高度是任意一节点到叶子节点的距离。 弄清楚高度和深度,就方便选择正确的遍历方式。对于高度应该是从二叉树的下面从上面开始计算,所以采用后序遍历方式较为方便,而深度是从上往下计算的,应该用前序遍历。而对于本题,所求的是最大深度,那么高度和深度是相等的。

递归法

1、确定函数参数和返回值:参数是传入根节点,返回值是最大深度,即为int

int maxDepth(TreeNode* root);

2、确定终止条件:空节点,返回0。

if (root == NULL) return 0;

3、确定单层递归逻辑:先求左子树的深度,再求右子树的深度,最后取它们深度的最大值后+1就是二叉树的最大深度。

int leftDepth = maxDepth(node->left);
int rigthDepth = maxdepth(node->right);
int depth = max(maxDepth, maxDepth) + 1;
return depth;

精简后整体代码

class solution{
public:
    int maxDepth(TreeNode* root){
        if (root == NULL) return 0;
        return max(maxDepth(root->left), maxDepth(root->rgiht)) + 1;
    }
};

111.二叉树的最小深度

题目链接:二叉树的最小深度

视频讲解:一看就做,一写就错!

        对于此题,只要搞清楚最小深度含义,就能在对最大深度的理解上完成。根据题意:最小深度是从根节点到最近叶子节点的最短路径上的节点数量。重点是叶子节点,其左右孩子都为空节点。所以在递归要时加上对左右孩子的判断。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int minDepth(TreeNode* root) {
        if (!root) return 0;
        int leftDepth = minDepth(root->left); // 左边最小
        int rightDepth = minDepth(root->right); // 右边最小
        // 最小深度是要满足处于最小深度的节点的左右节点都是空的
        if (!root->left && root->right)
            return rightDepth + 1;
        if (root->left && !root->right)
            return leftDepth + 1;
        int depth = 1 + min(leftDepth, rightDepth);
        return depth;
        // 其实可以更精简,写的细一点方便理解,后序遍历
    }
};

222.完全二叉树的节点个数

题目链接:完全二叉树的节点个数

视频讲解:理解普通二叉树和完全二叉树的区别!

        此题用普通二叉树遍历的方法也可以做,但是需要遍历每个节点。既然是完全二叉树,我们就要运用它的特性。如果是满完全二叉树,则节点的个数是 2 ^ 树深度 - 1。如果不是满的,从左右两边往下遍历,一定会有左孩子或右孩子为满二叉树(节点的左右孩子为空也算满的),这样可以再用公式计算。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
// 时间复杂度:O(log n × log n)
// 空间复杂度:O(log n)
class Solution {
public:
    int countNodes(TreeNode* root) {
       if (!root) return 0;
       TreeNode* left = root->left;
       TreeNode* right = root->right;
       int cntLeft = 0;
       int cntRight = 0;
       while (left) // 左子树的深度
       {
           left = left->left;
           cntLeft++;
       }
       while (right) // 右子树的深度
       {
           right = right->right;
           cntRight++;
       }
       if (cntLeft == cntRight) // 递归终止条件
        {
           return (2 << cntLeft) - 1;
       }

       int numLeft = countNodes(root->left);
       int numRight = countNodes(root->right);
       return (numLeft + numRight) + 1;
    }
};

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值