递归真的这么难?我!不!信!

说到递归,学习过的筒子们应该都不陌生了吧。

陌生是不陌生,知道有这么一个东西,但是真心不会做呀!不要慌,其实我也不大会做。。。

所以递归真的有那么难吗?没错,我觉得他真的不是很简单(至少对于我来讲,那些一看就会的就请绕道了哈,我就不撵你们了)

还记得刚开始接触递归的时候,应该是那个斐波那契数列了。然后后面学习数据结构,用的最多的就是在树里面了,反正学的是云里雾里,遇到递归题目自己怎么想也想不起来,一看答案就好像知道:哎,好像是这么回事!然后自己再写,还是不会写!啊这,可能这就是一废物吧。。。

没有办法,为了“生存”,还是得学啊!前段时间就在leetcode上找了几题简单的树的题目来做,刚拿到题目,感觉和前面一摸一样:一看就会,一做就废。这谁顶得住啊!不行,这还得了,看题解,抄也要抄上去,然后就抄了几题,你还憋说,好像有点作用,大概好像似乎几乎也许是在五一前一天我大学生涯中最后一节课堂上,我自己好像独立做出来了一道简单的递归题目,那家伙把我高兴的(好没出息),就突然感觉到递归题目好像是有那么一丝丝规律的?

所以就想把做题目的整个思路记录下来,虽然是挺简单的一道题(对我而言也许不是),也许对递归的理解能更加深入一些,虽然这只是一个开始,但可能也是一个结束(开玩笑!)它就是一个开始,后面还要通过大量的练习来理解,争取能掌握递归的精髓!(我应该能坚持 吧?)

我是这样理解递归的?

ok接下来言归正传!我将把我对递归的那么一点点“灵感”,希望帮助自己,也希望帮助你们!
大家能想到这个问题,那么一定也查了很多关于递归的文章或者资料,可能有些文章会告诉你递归的一些要素:

  1. 明确递归函数的目的
  2. 递归结束的条件
  3. 找函数的等价关系式

这是我原来查到的,应该是在去年了吧。这么一看似乎递归真的很简单,但是我刚开始接触的时候,还是不会这么去思考,我总想将它的每一次递归调用想清楚(现在想来我可能是疯了),每一次调用函数的返回值,输入值等等,我就开始在脑子里面开始想了,不过结果可想而知,想着想着就崩了,做TMD递归,LZ不做了。。。不知带其他同学有没有这种做递归的思维,反正这就是原来的我(现在其实也还有这种冲动。。)

但是递归不是这么做的!你得慢慢转变这种思想,刚开始学习的时候这么想应该很正常,但是当你发现你想不明白了以后就要回头了。我也正在努力改变,争取早日重新做人。。。呸呸呸!

我现在的感觉就是:做递归,要看整体,不要看局部!

  1. 看函数的返回值是什么?
  2. 看函数的输入参数值是什么?
  3. 递归结束条件(也可以叫做特殊情况)
  4. 整合上述信息,得到最终结果!

是不是有那么点感觉了呢?什么,还没有!?没关系,我们来结合一个例子看一看撒。没错这个例子就是我那天在leetcode上做出来的一个题目。这个题目四这样说滴:

例子:将有序数组转换为二叉搜索树

(leetcode第108题 简单题!难得我估计也做不出来。。。)

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
在这里插入图片描述
在这里插入图片描述

好,当拿到题目的时候,我们先别着急做,先弄明白到底要干啥?他要求我们将一个有序的数组转换成高度平衡的二叉搜索树。

首先从整体看问题,那我们就从数组中间将数组分成两部分,左边的一部分作为左子树,右边的一部分作为右子树,然后最中间的树作为根节点;这样既能保证平衡还能保证为搜索树。ok想到这里就足够了,不要再多想了!

接下来就按照上面的步骤:

  • (1)返回值类型:这个返回值类型就是一个节点呀,那我们想了,那最后返回的肯定是树的根节点;
  • (2)参数类型:这个参数是要转换成平衡二叉树的数组,因为每次要有左子树和右子树,所以要对原数组进行从中间分割,所以这里定义了一个split函数。
  • (3)递归结束条件:对于递归结束条件,我们可以把它看作为特殊情况:这里就是,当这棵树为空的时候,就直接返回空即可;而如果这棵树刚好只有结果,那直接返回根节点就好;
  • (4)最后就是将上面得到的信息进行整合了!总体来看就是将返回的左子树的根节点和右子树的根节点与整个树的根共同生成一个新的搜索树!

我感觉我说的还是挺乱的,下面是具体实现代码,大家可以参考理解!总之还是一句话,从整体上来看问题!

/**
 * 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 {
    // 定义分割数组的函数
    vector<int> split(vector<int>& vec, int begin, int end){
        vector<int> result;
        int i = 0;
        for(i = begin;i < end; i++)
            result.push_back(vec[i]);
        return result;
    }
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        int size = nums.size();

        // 递归结束的条件(可以理解为特殊情况)
        if(size == 0) return nullptr;
        if(size == 1)
        {
            TreeNode* node = new TreeNode(nums[0], nullptr, nullptr);
            return node;
        }

        // 将问题拆分成相同的子问题
        int mid = size/2;
        vector<int> left_vec = split(nums, 0, mid);
        vector<int> right_vec = split(nums, mid+1, size);

        // 调用函数实现递归
        TreeNode* left = sortedArrayToBST(left_vec);
        TreeNode* right = sortedArrayToBST(right_vec);
        // 利用左子树和右子树形成最终的树
        TreeNode* node = new TreeNode(nums[mid], left, right);

        return node;
    }
};

因为我也是最近开始补这一块的知识,也就只是记录了我的所思所想,难免会有一些错误,也可能会有说的含糊不清的地方,欢迎大家指出,我们一起交流学习进步!

Keep Learning! Keep Moving!

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
在给出的代码中,有一个递归jiecheng(int a),用于计算阶乘。其中,如果a等于0或1,就返回1.0,否则返回a乘以调用jiecheng(a-1)的结果。这样就实现了每次调用时改变形参a的值,逐步递减,直到达到结束条件。同样地,还有一个递归sum(int b),用于计算1!到b!的和。如果b等于1,就返回jiecheng(1),否则返回jiecheng(b)加上调用sum(b-1)的结果。在主方中,通过Scanner类获取用户输入的数x,并输出sum(x)的结果。 所以,求1!到5!的和可以按照如下步骤进行计算: 1. 定义一个方jiecheng,实现计算阶乘的功能。 2. 定义一个方sum,实现计算1!到b!的和的功能。 3. 在主方中,通过Scanner类获取用户输入的数x。 4. 调用sum(x),并输出结果。 下面是示例代码: ```java import java.util.Scanner; public class Test1 { public static double jiecheng(int a) { if (a == 0 || a == 1) { return 1.0; } return a * jiecheng(a - 1); } public static double sum(int b) { if (b == 1) { return jiecheng(1); } return jiecheng(b) + sum(b - 1); } public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.println("输入一个数,返回遍历阶乘和"); int x = scan.nextInt(); System.out.println("总和为 " + sum(x)); } } ``` 通过运行以上代码,可以得到1!到5!的和为 153.0。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [递归调用求1!+2!+3!...Java详解](https://blog.csdn.net/m0_56079407/article/details/119056102)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

MYH永恒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值