开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情
小白学算法(4)-递归
递归是将重复步骤进行简化的利器--无邪苦
递归三部曲
1.找中止条件
2.找返回值
3.找本层递归应该做什么
对于初学递归的同学,肯定是很迷糊的,因为他们想的太深,总会一层一层找到最后一层,然后返回值来到上一层,这样就导致都不知道在干嘛。
因为我也是这样的 🥲,但以后写递归时,请务必记住这三部曲,接下来就通过实例来进行讲解。
1.斐波拉契
这道题是很经典的问题,因为它的解法多样,这里我们讲解递归,所以使用递归。
斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1
1)找到递归条件
通过该数列知道n<2时n的值就等于数列值,易得
if(n<2)
return
2)找返回值
返回值上面的题中也写出来了F(n) = F(n - 1) + F(n - 2),其中 n > 1
return fib(n-1) + fib(n-2);
3)本层递归应该做什么
斐波那契并没有什么操作,所以本层没有操作
4)完整代码
int fib(int n){
if (n<2) {
return n;
} else {
return fib(n-1) + fib(n-2);
}
}
虽然可以使用递归解出斐波那契数列,但是它的解题效率非常低,所以很多时候会导致超时,下图也看得到进行了很多无意义的操作,但本体只是为大家介绍递归方法而已,所以想要知道其他更好的解法,可以去百度一手,此处不介绍。
2.
通过上面的引入,相比各位帅读者觉得递归很简单,但是实际递归很麻烦,因为它的一个关键点找返回值和本层做什么经常不好找到,如下题
head = [1,2,3,4]
输出:[2,1,4,3]
1)找递归条件
面对链表问题,并且参数是head 头节点的时候,
第一个终止条件便是此时head是否为空 head==NULL
题目说明是进行两两交换所以此时链表只有一个节点就自然结束了 head->next=NULL
综上
if(head==NULL||head->next==NULL)
return head;
2)找返回值
这一步找起来很麻烦,不知道返回什么,可以看下本函数的返回值ListNode*一个节点,但返回什么节点
两两交换,那么肯定是两个节点一组,我们把实例分为两组
[1,2,3,4]->[1,2] ,[3,4] 进行交换
[2,1],[4,3] ,我们知道节点是数据域+指针域,那么数据域倒是交换了,那么指针域呢
所以我们就明白了,返回的节点是下一组的头节点,然后通过本组的后一个节点进行连接,这样就成功完成转换了
//进行分组,那么函数传入的参数肯定是下一组的头节点
ListNode *next=head->next;
//交换后 该组的后一个节点肯定就是之前头节点撒,所以是head-next
head->next=swapPairs(next->next);
3)本次递归做什么
继续上个步骤
分了组后并且进行了连接,此时情况就是
[2,1->4,3]
这样两组就连接在一起了,但是我们一组里面的两个节点没有连接啊
//此时 [2->1->4,3],有帅读者说4怎么不跟3连接,😉因为那是下一层干的事了,我们只关注这一层,递归切忌跑其他层了
next->next=head;
4)结束
转换后的链表由 [1->2]--->[2->1],所以原本的头节点便不是头节点了
return next;
5)完整代码
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
//1.找递归终止条件
if(head==NULL||head->next==NULL)
return head;
//2.找返回值
ListNode *next=head->next;
//进行下一部分的遍历 那么头节点就是下下个节点
head->next=swapPairs(next->next);
//3.本次递归做什么
//递归后 下一个节点就成为上一个节点
next->next=head;
return next;
}
};
通过一易一中等题的解释,各位帅读者是否对递归有了一个很好的了解,希望给你带来收获,感谢观看。