版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37014990/article/details/79936051
设斐波那契数列,求第N项的值:
{1, 1, 2, 3, 5, 8, 13, 21, 34...}
斐波那契数列规律:
从第3项开始,每一项都等于前两项之和,即:当前值 = 前一项值 + 前前一项的值
从前人总结的规律来看,解决无非两种,方案如下:
方案一,利用数学公式,即递归表达式:
F(n) = F(n-1) + F(n-2),(n>=2)
递归公式出来,代码就好写了,但要注意边界条件。
/**
*
* 算法:斐波那契数列
*/
public class Fibonacci {
public static int fibonacci(int n){
//参数检查
if(n < 0) return -1;
//n = 1, n = 2的情况
if(n == 1 || n == 2) return 1;
//递归
return fibonacci(n - 1) + fibonacci(n - 2);
}
@SuppressWarnings("resource")
public static void main(String[] args) {
System.out.println("请输入第n项:");
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int result = fibonacci(n);
System.out.println("第" + n + "项的值为:" + result);
}
}
注意,递归求解斐波那契数列,存在极大问题,如果求第200项的值,时间就有点吓人,这不是一般计算机能承受的。
读者百度一波,就会知道使用递归求斐波那契,时间复杂度为指数阶的算法,所有很难受。
那么,我们可不可以改进一波呢?
且看,方案二:利用数组记录前两项的值,则只需要做一次加法就可以得到当前项。
public class Fibonacci {
public static int fibonacci(int n){
//参数检查
if(n < 0) return -1;
//声明一维数组
int[] arr = new int[n];
//初始化
arr[0] = 1; //第一项
arr[1] = 1; //第二项
//第三项开始,对应数组下标2
for(int i = 2, len = arr.length; i < len; i++){
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr[n - 1];
}
@SuppressWarnings("resource")
public static void main(String[] args) {
System.out.println("请输入第n项:");
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int result = fibonacci(n);
System.out.println("第" + n + "项的值为:" + result);
}
}
很明显,为了降低时间复杂度,我们使用了一个额外数组。
额,没错。用空间换时间,的确是个好办法。
但是,我们再思考一波,既然我们只想得到第n项的斐波那契的值,那么我们是否可以使用迭代法?
我们只保存中间结果,便于进行下次的计算:
public static int fibonacci(int n){
//参数检查
if(n < 0) return -1;
int s1 = 1; //第一项
int s2 = 2; //第二项
for(int i = 3; i <= n; i++){
s2 = s1 + s2; //辗转相加
s1 = s2 - s1; //记录前一项
}
return s2;
}
写到这里,方案3是推荐的方法。
好了,笔者只写到这里,如有错误,欢迎指正。