您的位置:首页 > 其它

斐波那契数列相关问题总结

2017-10-02 17:32 246 查看

一. 原问题

在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*),即从第三项开始,每一项等于前两项之和。

输入格式:输入包括一行,包括一个整数N (0≤N≤50)。

输出格式:输出包括一行,包括一个整数,为斐波那契数列的第 N 项的值。

递归方法

时间复杂度为O(2^n)。

import java.util.Scanner;

public class Fibonacci_1 {

public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
long f = fib(n);
System.out.println(f);
}

public static long fib(int n) {
if(n == 0){
return 0;
}else if (n == 1){
return 1;
}else {
return fib(n - 1) + fib(n - 2);
}
}
}


数组存储,动态规划

当一个问题可以分解成若干重复的子问题时,运用动态规划的思想:只需要将子问题求解一次,以后再遇到,直接调用,所以新建一个数组用于存储子问题的结果。(以空间换时间)

import java.util.Scanner;

public class Fibonacci_2 {

static Scanner input = new Scanner(System.in);
static int n = input.nextInt();
static long[] result = new long[n + 1];

public static void main(String[] args) {
long f = fib(n);
System.out.println(f);
}

public static long fib(int n) {
long f = 0;
if(n == 0){
f = 0;
}else if (n == 1){
f = 1;
}else if (result
> 0){
return result
;
}else {
f = fib(n - 1) + fib(n
4000
- 2);
}
result
= f;
return f;
}
}


递推方法

时间复杂度为O(n)

import java.util.Scanner;

public class Fibonacci_3 {
public static void main(String[] args) {
long f0 = 0;
long f1 = 1;
long f = 0;
Scanner input = new Scanner(System.in);
int n = input.nextInt();

if(n == 0){
f = 0;
}else if(n == 1){
f = 1;
}else {
for(int i = 2; i <= n; i++){
f = f0 + f1;
f0 = f1;
f1 = f;
}
}

System.out.println(f);
}
}


矩阵相乘算法

推导过程:





由此演变成了求

此矩阵的(n - 1)次方的过程。

import java.util.Scanner;

public class Fibonacci_4{

public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
long f = fib(n);
System.out.println(f);
}

public static long[][] baseMartrixMulti(int n) {
long[][] result = {{1, 0}, {0, 1}};//单位阵
long[][] base = {{1, 1}, {1, 0}};
long[][] temp = {{1, 0}, {0, 1}};
for (int i = 0; i < n; i++){
result[0][0] = temp[0][0] * base[0][0] + temp[0][1] * base[1][0];
result[0][1] = temp[0][0] * base[0][1] + temp[0][1] * base[1][1];
result[1][0] = temp[1][0] * base[0][0] + temp[1][1] * base[1][0];
result[1][1] = temp[1][0] * base[0][1] + temp[1][1] * base[1][1];
temp[0][0] = result[0][0];//特别注意,数组赋值赋的是引用,不能直接temp = result;
temp[0][1] = result[0][1];
temp[1][0] = result[1][0];
temp[1][1] = result[1][1];
}
return result;
}

public static long fib(int n) {
long f = 0;
if(n != 0){
long[][] trans = baseMartrixMulti(n - 1);
f = trans[0][0];//意义为下两条注释的语句
//long[][] bas = {{1}, {0}};
//f = trans[0][0] * bas[0][0] + trans[0][1] * bas[1][0];
}
return f;
}
}


矩阵相乘和乘方可以单独抽象出来函数,此处只是为了解决固定矩阵的乘方问题,没有给出普适代码,若有需要参考 矩阵乘法求斐波那契数列

此过程中发现乘方优化算法,参考 乘方的优化算法,可结合到矩阵乘方,待研究后贴出代码。

公式法



万能的数学家得出斐波那契数列通项公式如上,推导过程略(其实是因为看不懂,有兴趣自行百度 orz)。又称为“比内公式”,是用无理数表示有理数的一个范例。

代码实现如下:

import java.util.Scanner;

public class Fibonacci_5 {

public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
long f = (long)((Math.pow((1 + Math.sqrt(5)) / 2, n) - Math.pow((1 - Math.sqrt(5)) / 2, n)) / Math.sqrt(5));
System.out.println(f);
}
}


二. 引申问题

爬楼梯问题

假设你现在正在爬楼梯,楼梯有 n 级。每次你只能爬 1 级或者 2 级,那么你有多少种方法爬到楼梯的顶部?

输入格式:第一行输入一个整数 n(1≤n≤50),代表楼梯的级数。

输出格式:输出爬到楼梯顶部的方法总数。

其实相当于斐波那契问题,只是初始条件改变。f(1) = 1, f(2) = 2, n > 2时,f(n) = f(n - 1) + f(n - 2) 。 (若用矩阵运算可以将base矩阵减少一阶,也可以虚拟假设 f(0) = 1)

任选一种以上方法给出代码:

import java.util.Scanner;

public class Climb {
public static void main(String[] args) {
long f0 = 1;
long f1 = 1;
long f = 0;
Scanner input = new Scanner(System.in);
int n = input.nextInt();
if(n == 1){
f = 1;
}else{
for(int i = 2; i <= n; i++){
f = f0 + f1;
f0 = f1;
f1 = f;
}
}
System.out.println(f);
}
}


疯狂跳台阶

(题目来源于http://blog.csdn.net/xingyanxiao/article/details/47055973

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

因此,

。f(1)=1,f(2)=2。

代码略。

兔子问题

已知第一个月有一对刚出生的兔子,从出生第三个月起,一对兔子每个月可以生一对小兔子。假如没有发生死亡,则第一个月开始,第N个月后会有多少对?

这里以对为单位,从第一个月开始,每个月总共的兔子数量就是1, 1, 2, 3, 5, 8, 13……可以看出前两个月为1,从第三个月开始,当月的数量为前两个月数量之和,所以 f(n) = f(n - 1) + f(n - 2)(n > 2)。同时f(1) = 1, f(2) = 1。

代码实现同标准数学问题。

类似斐波那契问题还有很多,注意递推公式的推导即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: