我的第一个动态规划程序(试图用递归求斐波拉契数)

本文介绍了使用递归和动态规划方法解决斐波那契数列问题,通过优化减少重复计算,提高效率。从简单的递归实现到引入备忘表优化,再到最终使用通项公式简化计算,展示了动态规划在解决重复子问题问题上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、这是一般的递归(指数爆炸型,时间复杂度O(1.618^n)):

#include <iostream>
#include <cstdio>
using namespace std;

__int64 Fib(int n)
{
	if(n == 1 || n == 2)
		return 1;
	return Fib(n - 1) + Fib(n - 2);
}

int main(void)
{
	int n;
	while(cin >> n)
		printf("%I64d\n", Fib(n));
	return 0;
}

2、今天看了动态规划的入门,觉得建备忘表的方法挺不错的,也是符合人的思维的(这很重要),于是就类比,写了带备忘表的递归求斐波拉契数,这应该是以空间换时间吧,备忘表是全局的,一但建起,之后的就好办了。

#include <iostream>
#include <cstdio>
using namespace std;

__int64 aFib[90] = {0};				//	aFib[] correspond to Fib(), and global!

__int64 Fib(int n)
{
	if(n == 1 || n == 2)
		return 1;
	if(aFib[n - 1] == 0)			//	Fib(n-1) have been not calculated
		aFib[n - 1] = Fib(n - 1);
	if(aFib[n - 2] == 0)			//	Fib(n-2) have been not calculated
		aFib[n - 2] = Fib(n - 2);
	return aFib[n - 1] + aFib[n - 2];
}

int main(void)
{
	int n;
	while(cin >> n)
		printf("%I64d\n", Fib(n));
	return 0;
}

这是我学习动态规划的第一个应用,纪念一下!虽然还没充分体现动态规划(求最优解)的魅力。继续学习中。。。

2012/4/8 更新

原来这种方法叫 搜索+动态规划,顺便简化了第二个程序:

#include <iostream>
#include <cstdio>
using namespace std;

__int64 aFib[90] = {0, 1, 1};	//	aFib[] correspond to Fib(), and global!

unsigned __int64 Fib(const unsigned int n)
{
	if(aFib[n] == 0)			//	Fib(n) have been not calculated
		aFib[n] = Fib(n - 1) + Fib(n - 2);
	return aFib[n];
}

int main(void)
{
	int n;
	while(cin >> n)
		printf("%I64d\n", Fib(n));
	return 0;
}


2012/5/11 更新

通项公式法,时空复杂度都是O(1)

#include <iostream>
#include <cstdio>
using namespace std;

int main(void)
{
	int n;
	while(cin >> n)
		printf("%.0f\n", 0.4472135955 * pow(1.618033988745, n) );
	
	return 0;
}


<think>嗯,用户问的是如何用递归解斐波那契列的第n个。首先,我得回顾一下斐波那契列的定义。斐波那契列是前两个都是1,从第三个开始每个等于前两个之和,也就是F(n) = F(n-1) + F(n-2),基础情况是F(1)=1,F(2)=1。 接下来,我需要考虑用户的需。他们可能刚开始学习递归,想通过一个经典例子来理解递归的工作原理。不过,用户可能没有意识到递归在计算斐波那契列时的效率问题。比如,计算较大的n值时,递归会有大量的重复计算,导致性能低下。这时候,我需要解释清楚递归的优缺点,以及可能的优化方法,比如记忆化递归或迭代法。 然后,用户之前的问题是关于阶乘的递归解,所以可能对递归有一定的了解,但可能还没有接触到更复杂的情况。这时候需要对比阶乘递归和斐波那契递归的不同,指出斐波那契递归会分解为两个子问题,而阶乘只是一个,所以效率差异更大。 另外,用户可能还关心代码实现的具体细节,比如基础条件的处理,递归调用的结构,以及如何测试代码的正确性。需要提供一个清晰的Python示例,并展示运行结果,比如前10项的斐波那契,让用户能够直观看到效果。 还要注意用户可能提出的相关问题,比如递归的缺点、优化方法、其他应用案例等,提前在回答中预判并给出简要说明,帮助用户全面理解问题。同时,提醒用户在实际应用中可能遇到的栈溢出问题和性能问题,尤其是在处理大n时的注意事项。 总结来说,回答需要结构清晰,先介绍概念和递归思路,再给出代码示例和结果,最后讨论优缺点和相关优化方法,确保用户不仅学会如何用递归实现,还能理解其局限性和改进方向。</think>递归是解决斐波那契列问题的经典方法之一。斐波那契列的定义为: - 第1项和第2项为1:$F(1) = 1$, $F(2) = 1$ - 第$n$项($n>2$)为前两项之和:$F(n) = F(n-1) + F(n-2)$ 通过递归,我们可以将问题分解为更小的子问题,直到达到基础情况(即$n=1$或$n=2$)。 --- ### **递归解思路** 1. **基础条件**:当$n=1$或$n=2$时,直接返回1。 2. **递归步骤**:当$n>2$时,返回$F(n-1) + F(n-2)$。 --- ### **Python代码示例** ```python def fibonacci(n): if n == 1 or n == 2: # 基础情况终止条件 return 1 else: return fibonacci(n-1) + fibonacci(n-2) # 测试前10项 for i in range(1, 11): print(f"第{i}项斐波那契:{fibonacci(i)}") ``` --- ### **运行结果** ``` 第1项斐波那契:1 第2项斐波那契:1 第3项斐波那契:2 第4项斐波那契:3 第5项斐波那契:5 第6项斐波那契:8 第7项斐波那契:13 第8项斐波那契:21 第9项斐波那契:34 第10项斐波那契:55 ``` --- ### **递归的局限性** 1. **重复计算问题**: 递归会重复计算大量子问题(例如,计算$F(5)$时需要重复计算$F(3)$和$F(2)$)。时间复杂度为$O(2^n)$,效率极低。 2. **栈溢出风险**: 当$n$较大时(如$n=40$),递归深度过大会导致栈溢出错误。 --- ### **优化方法** 1. **记忆化递归(Memoization)**: 使用缓存存储已计算的斐波那契,避免重复计算,将时间复杂度优化到$O(n)$。 ```python def fibonacci_memo(n, memo={}): if n in memo: return memo[n] if n <= 2: return 1 memo[n] = fibonacci_memo(n-1, memo) + fibonacci_memo(n-2, memo) return memo[n] ``` 2. **迭代法**: 通过循环直接计算,时间复杂度$O(n)$,空间复杂度$O(1)$。 ```python def fibonacci_iter(n): a, b = 1, 1 for _ in range(2, n): a, b = b, a + b return b ``` --- ### **递归的适用场景** 递归适合问题天然可分且子问题无重叠的场景,例如: - 阶乘计算($n! = n \cdot (n-1)!$) - 二叉树遍历(前序、中序、后序) - 汉诺塔问题 - 分治算法(如快速排序) --- ### **总结** 递归解斐波那契列简洁直观,但效率低下,适合教学或小规模计算。实际应用中建议使用记忆化递归或迭代法优化性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值