代码随想录第十六天 leetcode 104、559、111、222(二叉树)

104. 二叉树的最大深度

首先需要明白最大深度是什么,之前的题也刷过,不过是用层序法做的。最大深度等于根节点的高度,深度是从上往下算的,高度是从下往上算的。这里使用递归的后序遍历(为什么呢,暂时还没有自己的方法论,先跟着卡哥的思路写),从叶子结点开始计算节点的高度,直到算到根节点时的高度即为最大深度。
下面是递归三部曲:

  1. 输入传入的是结点,输出是深度int
  2. 终止条件是结点为NULL时,此时结点时没有高度的,返回0
  3. 递归的单层逻辑,还是左右中的处理顺序,这里说一下最后返回的时候是返回上一层结点,所以返回值为1+当前结点的高度。同时因为是要找二叉树的最大深度,返回的应该是同一层结点中较大的那个结点的高度。
    在这里插入图片描述
    例如当left为9,right为20时,9的高度为1,20的高度为2,所以这一层返回的应该是2 + 1。

代码如下:

int maxDepth(TreeNode* root) {
        if(root == NULL) return 0;
        int left = maxDepth(root->left);
        int right = maxDepth(root->right);
        return 1 + max(left,right);
    }

当然,迭代中的层序遍历完美符合寻找深度,也符合正常的思维,但是递归法还是需要掌握,只能说先积累经验吧。

559. N 叉树的最大深度

N叉树也是一样的,只不过在处理结点的时候套用一个循环来计算高度。
代码如下:

int maxdepth(node* root) {
        if (root == 0) return 0;
        int depth = 0;
        for (int i = 0; i < root->children.size(); i++) {
            depth = max (depth, maxdepth(root->children[i]));
        }
        return depth + 1;
    }

先使用一个depth来记录这一层结点的高度,再依次进行对比找出最大的高度,最后返回的时候+1。

111. 二叉树的最小深度

本题使用迭代的层序遍历也是很简单,并且可以忽略根节点下左右子树其中一个为空的情况。这里使用递归的后序遍历。上一题最后返回的是max(leftdep , rightdep),那么本题返回的应该是min(leftdep , rightdep),但是需要考虑刚刚说的节点下左右子树其中一个为空的情况,否则不管另一个不为空的孩子下面有多少结点,最后返回的答案为1,也就是根节点的高度。
在这里插入图片描述
比如说这个就是左子树为空的情况。(力扣上的二叉树可视化功能很好用,方便自测)

递归三部曲:

  1. 输入是结点,输出是深度int
  2. 终止条件这里需要添加上述的特殊情况,正常情况下为root == NULL
  3. 单层递归逻辑和上一题差不多,属于后序遍历

代码如下:

int minDepth(TreeNode* root) {
        if(root == NULL) return 0;
        //首先记录当前结点的高度,以便作为特殊情况的返回值
        int left = minDepth(root->left);
        int right = minDepth(root->right);
        //两种特殊情况
        if(root->left == NULL && root->right != NULL){
            return 1 + right;
        }
        if(root->left != NULL && root->right == NULL){
            return 1 + left;
        }
        //正常情况下的返回值
        return 1 + min(left,right);
    }

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

本题使用常规的遍历模板,再使用一个计数,遍历后返回结果就可以得出结点个数。
考虑到题目给出的是完全二叉树,所以使用完全二叉树的特性来做,并且使用递归法。
这里使用完全二叉树的特性,只有最底层结点没有填满外,以上的结点都是满的;所以只要判断子树是否为完全二叉树,并知道其深度,就能计算出结点个数。如果一棵树的左下角的结点和右下角结点的深度相等,那么他就是一颗完全二叉树。这样如果一棵子树为完全二叉树的话,只用遍历其底层最外侧的左右结点就可以计算出结点个数。
递归三部曲:

  1. 输入是结点,输出是结点及其子树的个数int
  2. 终止条件:结点为空、判断一棵树是否为完全二叉树
  3. 单层递归逻辑:如果子树不是完全二叉树,那么进入单层递归逻辑。我发现这种返回值为int需要求深度高度个数的递归,都是后序。先把左右孩子递归结束,再分别用两个变量记录结果,最后return的时候根据题意处理。

代码如下:

int countNodes(TreeNode* root) {
        if(root == NULL) return 0;
        //通过外侧结点来判断子树是否是完全二叉树
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        int leftdep = 0;
        int rightdep = 0;
        while(left){
            left = left->left;
            leftdep++;
        }
        while(right){
            right = right->right;
            rightdep++;
        }
        if(leftdep == rightdep) return (2<<leftdep) - 1;
        int leftnum = countNodes(root->left); //这里是root的左右孩子,上面的root->left不是用来递归遍历的
        int rightnum = countNodes(root->right);
        return leftnum + rightnum + 1;
    }

这里2<<leftdep的移位运算符表示2的leftdep次方。

写给自己的总结(不知道对不对)

最近做的递归,返回类型都是int,也就是题目需要求的是什么的个数(一般是后序),这样一个递归函数就可以直接搞定,那么这种情况下递归函数最后return的值递归到最后也就是需要返回的答案,因为一层的递归需要统计的个数是在上一层的基础上计算的。这样这类题目(还没总结出来是哪类)的递归函数的写法就是:

  • 首先确定终止条件有没有特殊情况,如111和222
  • 然后就是对左右孩子的递归
  • 最后对递归出来的左右孩子的结果处理
    感觉基本就是一个后序的过程。

这里就是自己的刷题感悟,希望有大佬指正!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值