动态规划经典题目之三 斐波那契数列

问题描述

斐波那契数列 1 1 2 3 5 8 ... ... 求斐波那契数列的第n项和。

问题分析

    斐波那契数列的递推公式为 F(n) = 1,n=1,2; F(n) = F(n - 1) + F(n - 2), n >= 3;

采用递归的方式很容易写出代码,但是递归的代码虽然简单,却存在着大量的重复子问题,重复计算,时间复杂度高。例如,我们以求解F(5)为例,如下:

红色的部分都是重复求解的,这仅仅是n=5时,当n=30时,子结构重复求解会大大浪费时间,时间,空间都会爆掉。

                          

解法1:

    我们直观想到的是,既然会重复求解,那只要记录下来求解过的就行了,下次计算前,先看看有没有计算过,如果已经计算过就不需要再次计算,这就是备忘录算法。但是,当n过大时,递归层数过多,空间也会爆掉。

 

解法2:

    解法1是自顶向下进行递归求解。而DP是自底向上的求解问题,由初始状态一步步向上求的问题的解。对于斐波那契数列,初始状态为 F(1) = F(2) = 1, 那么我们可以依次求出 

F(3),F(4),... ...F(n) ,同样的子问题,也是只需要求解一次,大大提高了计算效率。

递归求法代码

#include <iostream>

using namespace std;

int fib(int N)
{
    if(N == 1)
        return 1;
    ifa(N == 2)
        return 1;
    return fib(N-1) + fib(N-2);
}

int main()
{
    int n;
    cin >> n;
    cout << fib(n) << endl;
}

备忘录算法

#include <iostream>

using namespace std;

int* fib_data;

int fib(int N)
{
	if(N == 1)
		return 1;
	if(N == 2)
		return 1;
	if(fib_data[N] > 0)
		return fib_data[N];
	else {
		fib_data[N-1] = fib(N-1);
		fib_data[N-2] = fib(N-2);
		return fib_data[N-1] + fib_data[N-2];
	}
}

int main()
{
	int n;
	cin >> n;
	fib_data = new int[n + 1];
	memset(fib_data,0,sizeof(int) * (n + 1));
	cout << fib(n) << endl;
}

DP代码

#include <iostream>

using namespace std;

long long dp_fib(int N)
{
	long long* fib_n = new long long[N + 1];
	fib_n[1] = 1;
	fib_n[2] = 1;
	for (int i = 3; i <= N; i++) {
		fib_n[i] = fib_n[i - 1] + fib_n[i - 2];
	}
	return fib_n[N - 1];
}

int main()
{
	int n;
	cin >> n;
	cout << dp_fib(n) << endl;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值