剑指offer面试题10——斐波那契数列&&青蛙跳台阶问题

题目一:求斐波那契数列顶的第n项

写一个函数,输入n,求斐波那契数列的第n项。Fibonacci数列的定义如下:

n=0,f(n)=0 n=1,f(n)=1, if n>1;f(n)=f(n-1)+f(n-2)

思路:

这个问题是比较常见的问题,用递归的方法我们可以很快的写出代码:

#include <iostream>、
using namespace std;

long long Fibonacci(unsigned int n)
{
	if (n <= 0)
		return 0;
	if (n == 1)
		return 1;
	return Fibonacci(n - 1) + Fibonacci(n - 2);
}

但是这个方法在效率上会有严重的问题,每次计算一个数都需要重复计算之前已经计算过的数,这是一种重复度非常大的计算方法。这里我们可以引入动态规划的思想,将计算好的前面的数据直接利用到后面的计算中去,比如用递推的方法,从第一项开始往后进行计算,这样每个数据只需要计算依次就可以求出最后的结果。或者用空间换取时间,用一个数组来储存计算过的值,当需要这个值的时候直接调用即可。

//从下到上进行递推
long long Fibonacci(unsigned n)
{
	int result[2] = { 0,1 };
	if (n < 2)
		return result[n];
	long long fibNMinusOne = 0;
	long long fibNMinusTwo = 1;
	long long fibN = 0;
	for (unsigned int i = 2; i <= n; i++)
	{
		fibN = fibNMinusOne + fibNMinusTwo;
		fibNMinusOne = fibNMinusTwo;
		fibNMinusTwo = fibN;
	}
	return fibN;
}
//开一个数组来记录之前计算过的值
#include <iostream>
#include<cstring>
using namespace std;
const int maxn = 1000;
int dp[maxn];


int F(int n)
{
	if (n == 0) return 0;
	if (n == 1) return 1;
	if (dp[n] != -1) return dp[n];
	else
	{
		dp[n] = F(n - 1) + F(n - 2);
		return dp[n];
	}

}

int main()
{
	memset(dp, -1, sizeof(dp));
}

题目二:青蛙跳台阶问题

  1. 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个n级台阶总共有多少种跳法。

        边界情况,如果n=1,那么只有一种跳法,n=2,有两种跳法。推广开来,当n>2时,第一次跳有两种选择,一是第一次跳1级,此时跳法的数目为后面剩下的n-1级台阶的跳法数目,即为f(n-1)。二是第一次跳2级,此时跳法的数目为后面剩下的n-2级台阶的跳法数目,即f(n-2)。那么就有f(n)=f(n-1)+f(n-2)。得到一个递推关系,我们惊讶的发现,这就是一个Fibonacci数列,前两项为1和2,后面每一项等于前两项的和。

2. 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
     f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n-(n-1)) + f(n-n)= f(0) + f(1) + f(2) + f(3) + ... + f(n-2)+f(n-1)
    f(n-1) = f(0) + f(1)+f(2)+f(3) + ... + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)
    so  f(n)=2*f(n-1)


    public int Jump3(int n) {
            if (n <= 1) {
                return 1;
            } else {
                return 2 * Jump3(n - 1);
            }
        }

也就是会有2^{n-1}种跳法。

4. 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个m级的台阶总共有多少种跳法。
   先列多项式(假设m>n):
   f(n) =  f(n-1) + f(n-2) + f(n-3) + ... + f(m-n)
   f(n-1) =   f(n-2) + f(n-3) + ... + f(m-n) + f(m-n-1)
   化简得:f(n) = 2f(n-1) - f(m-n-1)


复习:

求斐波拉契数列的递归写法会有很多重复计算,效率比较低,但是如果一定要用递归可以采用动态规划的方法,每次计算一个值就将其存到数组里面,这样下次需要这个值的时候就不需要再进行计算了。当然,最好还是用子夏而上的循环来进行计算,这样不需要借助辅助数组了。青蛙跳台阶的问题也要知道推导的方法。

二刷代码:

long long Finonacci(unsigned int n)
{
	int result[2] = { 0,1 };
	if (n < 2)
		return result[n];

	long long FinonacciOne = 1;
	long long FinonacciTwo = 0;
	long long FiN = 0;

	for (unsigned i = 2; i <= n; ++i)
	{
		FiN = FinonacciOne + FinonacciTwo;
		FinonacciTwo = FinonacciOne;
		FinonacciOne = FiN;
	}

	return FiN;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值