函数递归3

通过之前的文章函数递归1函数递归2,让大家了解到了基础的函数递归,这篇文章会通过一些经典的习题让大家熟练使用递归。

就像前面的图片一样函数不停的一层调用下一层,最后返回。需要掌握大事化小的思想,具体如何的实现是需要多个题目来练习的

今天就来做一下比较经典的斐波那契数列

这里我使用了力扣上的习题来做讲解

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给定 n ,请计算 F(n) 。

示例 1:

输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1
示例 2:

输入:n = 3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2
示例 3:

输入:n = 4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3

提示:

0 <= n <= 30

那我们先从题目解析开始

光看题目感觉有点让人云里雾里,所以可以举个例子  假设有一个斐波那契数列,该数列为0,1,1,那么之后的每一个都应该为之前两个数之和,所以下个数就应该是1+1也就是2。力扣的题目会在给了你其他的代码,你只需要直接实现这个函数就行了,它会提供多种测试用例来提供给你测试。这道题目是要求提供一个数,然后算出这个数的斐波那契数列各个数之和。

这里还是用刚才那个数列进行假设(1,1,2,3,5)这时力扣的后台就会给你提供5这个数字

此时5就应该等于2+3.划分出来2和3后,2=1+1,3=1+2;到了1之后就不能再向下化小了,但是3后面的2还可以继续化小,化成2=1+1,把所有的1加起来,第五个数字就应该为5

这里可以画一幅图给大家解释一下

 这里我再画一个递归的图解为例,帮助大家理解斐波那契数列

 这里我们可以再在vs2022上进行测试,可以根据力扣旁边的测试用例来,这里我就只使用一个,当n=3的时候

#define _CRT_SECURE_NO_WARNINGS 1//取消警告
#include<stdio.h>
#include<string.h>
int fac(int n);
int main() {
	printf("%d", fac(3));
	return 0;
}
int fac(int n) {
	if (n <= 1) {
		return 1;
	}
	else {
		return n + fac(n - 1);
	}
}

 这样一个简单的递归就完成了。,当然我们要学的不仅仅是这些,这里我把n改为50,再让程序算出第50个数

#define _CRT_SECURE_NO_WARNINGS 1//取消警告
#include<stdio.h>
#include<string.h>
int fib(int n);
int main() {
	printf("%d", fib(50));
	return 0;
}
int fib(int n) {
	if (0 == n) {
		return 0;
	}
	if (1 == n) {
		return 1;
	}
	return fib(n - 1) + fib(n - 2);
}

 大家可以照着代码敲一下,在自己的电脑上运行时,就会发现你等了许久,都没有计算出结果。这是为什么呢????

因为递归进行了大量的重复的计算,如果大家有兴趣,可以在自己的电脑上跑一下这个程序,大概需要5min左右。这里我用图片为大家解释一下原因

这样的图有点像数据结构中的树,当然按照这幅图依次计算,就会耗费大量的时间,直到第一个为1的斐波那契数列。在第一层需要计算2^0,第二行时计算2^1次,这样算到最后就需要2^49次,这样我们计算的效率就会非常低。

这里我也可以写一个代码让大家了解一下递归到底需要的时间

#define _CRT_SECURE_NO_WARNINGS 1//取消警告
#include<stdio.h>
#include<string.h>
int count = 0;
int fib(int n);
int main() {
	printf("%d\n", fib(20));
	printf("%d", count);
	return 0;
}
int fib(int n) {
	if (0 == n) {
		return 0;
	}
	if (1 == n) {
		return 1;
	}
	if (n == 3) {
		count++;
	}
	return fib(n - 1) + fib(n - 2);
}

这里我定义了一个全局变量count,每当递归到n=3的时候count就+1,最后运行一下可以看看到底需要进行多少次的计算

 当我们需要算斐波那契数列的第20个数的时候,fib(3)就被调用了3次

这样的题目我们会发现在计算大的数字的时候,计算机会耗费很多时间,这里我们也可以通过使用循环来计算。

这道题也可以这么想:

斐波那契数列无非就是第3个数就是第一个数+第二个数,第4个数就是第三个数+第二个数

所以经过循环思想的优化。我们也可以这样计算斐波那契数列

#define _CRT_SECURE_NO_WARNINGS 1//取消警告
#include<stdio.h>
#include<string.h>
int fib(int n);
int main() {
	printf("%d\n", fib(20));
	return 0;
}
int fib(int n) {
	int a = 1;
	int b = 1;
	int c = 1;
	//斐波那契数列的前两个数为1
	while (n >= 2) {
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}

但是这里其实包括了一点小技巧,本来斐波那契数列要计算第三个数c大家一般会想到初始化为0.可当n=1的时候,这样返回值就为0了,所以这里将c赋值为1。

到这里,函数的递归就差不多讲完了,剩下的只能靠读者们在不断刷题中灵活运用了,希望在以后的不管是考试还是竞赛都可以灵活使用递归

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值