// 题目:斐波那契数列
// 解法1:用递归的方式完成
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(fib(998));
}
public static int fib(int n) {
if (n <= 0) { // 如果n小于等于0就返回0
return 0;
}
if (n == 1) { // 如果n等于1就返回1
return 1;
}
return fib(n - 1) + fib(n - 2); // 否则进行递归
}
}
// 解法2:存储中间结果,避免了了大量的重复计算,可以使用递归或非递归完成
public class Main {
private static int[] arr = new int[999];
public static void main(String[] args) throws Exception {
System.out.println(fib1(998));
System.out.println(fib2(998));
}
// 非递归的方式完成
public static int fib1(int n) {
if (n <= 0) {
return 0;
} else if (n == 1) {
return 1;
}
int temp = 1;
int num1 = 0;
int num2 = 1;
while (temp != n) {
int t = num1 + num2;
num1 = num2;
num2 = t;
temp++;
}
return num2;
}
// 递归的方式完成
public static int fib2(int n) {
if (arr[n] != 0) { // 如果数组中保存了数据就返回,没有保存就进入递归
return arr[n];
} else {
if (n <= 0) {
arr[0] = 0;
return 0;
} else if (n == 1) {
arr[1] = 1;
return 1;
} else {
arr[n] = fib2(n - 1) + fib2(n - 2);
return arr[n];
}
}
}
}
// 解法3:求出斐波那契数列的通项,即可在O(1)时间复杂度求解
// 线性递推数列的特征方程:x^2 = x + 1,求出x1,x2,则斐波那契数列为f(n) = c1*x1^n+c2*x2^n
// 求出c1,c2即可得到斐波那契数列的通项
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(fib(8));
}
public static int fib(int n) {
double result = Math.sqrt(5) / 5 * Math.pow(((1 + Math.sqrt(5)) / 2), n)
- Math.sqrt(5) * Math.pow(((1 - Math.sqrt(5)) / 2), n); // 斐波那契数列的通项公式
return (int) Math.round(result);
}
}
// 解法4:使用矩阵相乘的方式,把问题转化成求矩阵的n-1次幂的第一行第一列的元素,复杂度O(logn)
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(fib(6));
}
public static int fib(int n) {
if (n <= 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
int[][] arr = { { 1, 1 }, { 1, 0 } };
return fibHelp(arr, n - 1)[0][0];
}
}
// 与常数的折半乘方一样,只不过现在变成矩阵了
public static int[][] fibHelp(int[][] arr, int n) {
if (n == 0) {
return new int[][] { { 1, 1 }, { 1, 1 } }; // 如果阶乘为0,则返回都是1的矩阵
}
if (n == 1) { // 如果阶乘为1,返回原矩阵
return arr;
}
int[][] temp = fibHelp(arr, n / 2);
int[][] result = new int[2][2];
result[0][0] = temp[0][0] * temp[0][0] + temp[0][1] * temp[1][0]; // 逐个元素计算,得到两矩阵的相乘结果
result[0][1] = temp[0][0] * temp[0][1] + temp[0][1] * temp[1][1];
result[1][0] = temp[1][0] * temp[0][0] + temp[1][1] * temp[1][0];
result[1][1] = temp[1][0] * temp[0][1] + temp[1][1] * temp[1][1];
if (n % 2 == 1) { // 如果阶乘为奇数则在乘一个原矩阵
int[][] temp1 = new int[2][2];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
temp1[i][j] = result[i][j];
}
}
result[0][0] = arr[0][0] * temp1[0][0] + arr[0][1] * temp1[1][0];
result[0][1] = arr[0][0] * temp1[0][1] + arr[0][1] * temp1[1][1];
result[1][0] = arr[1][0] * temp1[0][0] + arr[1][1] * temp1[1][0];
result[1][1] = arr[1][0] * temp1[0][1] + arr[1][1] * temp1[1][1];
}
return result;
}
}
解法四的原理