递归真的那么难?我!信!了!

上篇文章记录了我做递归题目的一点点灵感,然后我现在发现我高兴的太早了。。。

这不趁着五一假期结束之前赶紧又做了一题递归题目,然后经过我仔细分析,根据我前面总结的经验,感觉还好,用给的示例运行也是对的,然后我很高兴的点击了提交,果不其然,解答错误。。。。。

话不多说,来看看怎么错的吧!

题目

110. 平衡二叉树

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

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

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

在这里插入图片描述
在这里插入图片描述

提交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) {}
 * };
 */
class Solution {
    // 定义计算树深度的函数
    int tree_depth(TreeNode* node){
        // 递归结束条件(特殊情况)
        if(node == nullptr) return 0;
        if(node->left == nullptr && node->right == nullptr) return 1;

        // 递归调用
        int l = tree_depth(node->left) + 1;
        int r = tree_depth(node->right) + 1;

        // 最终返回结果
        return max(l, r);
    }
public:
    bool isBalanced(TreeNode* root) {
        /*
            可以将递归题目的解答分为3块:
                (1)第一块:递归结束条件(特殊情况),含有return语句
                (2)第二块:递归调用,调用函数本身,整体解决问题
                (3)第三块:返回最终结果,含有return语句
        */

        // 递归结束条件(特殊情况)
        if(root == nullptr) return true;
        // 计算左右子树的深度
        int left_depth = tree_depth(root->left);
        int right_depth = tree_depth(root->right);
        // 判断是否为平衡树
        if(fabs(left_depth-right_depth)>1) 
            return false;
        else 
            return true;

        // 递归调用
        bool left_tree = isBalanced(root->left);
        bool right_tree = isBalanced(root->right);

        // 最终返回结果
        return left_tree && right_tree;
    }
};

错误示例: [1,2,2,3,null,null,3,4,null,null,4]

刚开我有点懵,但是经过我仔细分析之后,我发现根本就没有实现递归,在计算第一次左子树和右子树的时候就return 了答案!但我们这个题目要求的是每一个节点都必须满足平衡二叉树的特点,所以就错了。。。

提交2(√):自顶向下

然后我就对代码稍微改动了一下,我先不return,我先把结果用一个变量记录下来,等递归完了一块返回,其实我改的时候还是有点懵的,不过感觉就是这个理,然后就对了。

/**
 * 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 {
    // 定义计算树深度的函数
    int tree_depth(TreeNode* node){
        // 递归结束条件(特殊情况)
        if(node == nullptr) return 0;
        if(node->left == nullptr && node->right == nullptr) return 1;

        // 递归调用
        int l = tree_depth(node->left) + 1;
        int r = tree_depth(node->right) + 1;

        // 最终返回结果
        return max(l, r);
    }
public:
    bool isBalanced(TreeNode* root) {
        /*
            可以将递归题目的解答分为3块:
                (1)第一块:递归结束条件(特殊情况),含有return语句
                (2)第二块:递归调用,调用函数本身,整体解决问题
                (3)第三块:返回最终结果,含有return语句
        */
        bool is = true;

        // 递归结束条件(特殊情况)
        if(root == nullptr) return true;
        // 计算左右子树的深度
        int left_depth = tree_depth(root->left);
        int right_depth = tree_depth(root->right);
        // 判断是否为平衡树
        if(fabs(left_depth-right_depth)>1) 
            is = false;
        else 
            is = true;

        // 递归调用
        bool left_tree = isBalanced(root->left);
        bool right_tree = isBalanced(root->right);

        // 最终返回结果
        return left_tree && right_tree && is;
    }
};

然后我去看了一下官方的题解,发现官方题解真的很间接,而我这。。。又臭又长,哎没办法,毕竟还是个小菜鸡,慢慢来吧,能运行成功就不错了(自我鼓励一下!)

然后通过看解析,发现有两种递归的方法:自顶向下和自底向上两种。我用的这种属于自顶向下,就是我相当于用了两遍递归,因为我需要计算每一个节点的深度,而计算节点的函数又是递归的,所以这样时间复杂度会很高!

请原谅我似乎刚了解了自顶向下和自底向上这两种递归方法。然后我又看了自底向上的递归方法。

提交3(√):自底向上

/**
 * 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 {
    // 自底向上递归
    int depth(TreeNode* node){
        if(node == nullptr)
            return 0;
            
        // 当到达树的最低端才会开始执行相应操作
        int l = depth(node->left);
        int r = depth(node->right);

        if(l == -1 || r == -1 || fabs(l-r) > 1)
            return -1;
        
        return max(l, r)+1;
    }
public:
    bool isBalanced(TreeNode* root) {
        return depth(root) >= 0;
    }
};

自底向上可以看到,在计算树的深度的时候,他刚开始是不进行操作的,先递归到树的最底部,然后在进行相应操作,如果出现非平衡现象就返回-1,否则就返回树的高度。这样就需要递归一次即可!时间复杂度会降低很多。

怎么朔呢,修行还不够,还得继续努力,熟能生巧吧,多做多练,没别人聪明,就得比别人努力一点呗!

Keep learning! Keep moving!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 我们可以使用以下函数来求n!:def factorial(n): if n == 0: return 1 else: return n * factorial(n-1)因此,要求用递归函数调用的方法求n!,可以使用上述函数,即:factorial(n)。 ### 回答2: n!是指从1乘到n的积,可以通过递归调用函数来求解。以下是使用函数递归调用的方法求n!的示例: ```python def factorial(n): if n == 0 or n == 1: return 1 else: return n * factorial(n - 1) n = int(input("请输入一个非负整数n: ")) result = factorial(n) print(f"{n}的阶乘是:{result}") ``` 在上述代码中,首先定义了一个名为factorial的函数,该函数接受一个非负整数n作为参数。如果n等于0或1,则直接返回1。否则,通过递归的方式调用函数自身,并将n减1作为参数传入函数。在递归调用中,将n与n的前一个数相乘,直到n等于0或1为止。 然后,通过输入函数获取用户输入的一个非负整数n,并调用factorial函数求解n的阶乘。最后,将结果打印输出。 使用递归调用函数求解n!的优点是代码简洁,易于理解。然而,如果n的值过大,递归调用可能会导致栈溢出的问题,因此在实际应用中需要注意控制递归的深度。 ### 回答3: 要求使用函数递归调用的方法求n!(n的阶乘)。首先,需要明确如何定义阶乘。n的阶乘是指从1到n所有正整数的乘积,即n! = 1 * 2 * 3 * ... * n。 为了使用函数递归调用,我们可以使用一个递归函数来计算n的阶乘。递归函数的基本思想是将大问题转化为规模较小的子问题,并通过不断地调用自身来解决子问题。 以下是一个用于计算n! 的递归函数的示例代码: ```python def factorial(n): # 递归结束的条件:当n = 0或n = 1时,直接返回1 if n == 0 or n == 1: return 1 # 递归调用自身,计算n的阶乘 else: return n * factorial(n-1) ``` 在以上代码中,递归函数factorial采用了以下逻辑: - 如果n等于0或1,就直接返回1,因为0!和1!都等于1。 - 如果n大于1,我们通过调用函数factorial(n-1)来计算(n-1)!,然后将结果乘以n,即n * factorial(n-1)。这样就得到了n!的值。 使用上述递归函数,可以方便地计算任意正整数n的阶乘。例如,对于n = 5,调用factorial(5),则会进行如下的计算过程: factorial(5) = 5 * factorial(4) = 5 * 4 * factorial(3) = 5 * 4 * 3 * factorial(2) = 5 * 4 * 3 * 2 * factorial(1) = 5 * 4 * 3 * 2 * 1 * factorial(0) = 5 * 4 * 3 * 2 * 1 * 1 = 120 因此,使用函数递归调用的方法,可以求出n的阶乘。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MYH永恒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值