费波纳茨数列求和(高效、不溢出)
费波纳茨数列指的是这样一个数列:1、1、2、3、5、8、13、21、34……
先看一种常用的递归实现:
public class Feibonaci { public static void main(String args[]) { System.out.println("第几个:" + fibonacci(20)); System.out.println("总数:" + sumFibonacci(20)); }
//第几个 public static int fibonacci(int n) { if (n <= 0) { return 0; } else if (n == 1 || n == 2) { return 1; } else { return fibonacci(n - 1) + fibonacci(n - 2); } }
//求和 public static int sumFibonacci(int n) { if (n <= 0) { return 0; } else if (n == 1) { return 1; } else { return fibonacci(n) + sumFibonacci(n - 1); } } }
上面的做法当n超过50,求和速度很慢,n再大数据会溢出
重新写另一种实现:
import java.math.BigInteger; /** * 费波纳茨数列{1,1,2,3,5,8,13,21} 后一项的值等于前两项的和 * * @author chenhening * @date 2017年4月21日 */ public class Feibonaci { public static BigInteger b[] = new BigInteger[100000];// 用数组存数列的值 public static BigInteger sum[] = new BigInteger[100000];// 数组里每个值表示前n个数的和 public static void main(String args[]) { System.out.println("第几个:" + get(50)); System.out.println("总数:" + sum(50)); } /** * 获取第index个值 * * @param index * @return * @date 2017年4月21日 * @author chenhening */ public static BigInteger get(int index) { if (index <= 0) return null; // 如果已经存值,直接返回 if (b[index] != null) return b[index]; // 第一个和第二个都是1 if (index <= 2) { b[index] = BigInteger.valueOf(1L); return b[index]; } BigInteger b1; if (b[index - 1] != null) { b1 = b[index - 1]; } else { // 递归取值 b1 = get(index - 1); } BigInteger b2; if (b[index - 2] != null) { b2 = b[index - 2]; } else { // 递归取值 b2 = get(index - 2); } // 前两个值的和 b[index] = b1.add(b2); return b[index]; } /** * 计算前index个数的和 * * @param index * @return * @date 2017年4月21日 * @author chenhening */ public static BigInteger sum(int index) { if (index <= 0) return null; if (index <= 2) { sum[index] = BigInteger.valueOf(index); return sum[index]; } return get(index).add(sum(index - 1)); } }
使用数组存储数据,保存每个计算过的值,效率比较高