斐波那契数列
斐波那契数列(Fibonacci sequence)是一个非常著名的数学序列,它是由意大利数学家莱昂纳多·斐波那契(Leonardo Fibonacci)在1202年的著作《计算之书》(Liber Abaci)中首次引入的。这个数列的定义如下:
- 数列的前两个数是 0 和 1。
- 从第三个数开始,每个数都是前两个数的和。
用数学公式表示,斐波那契数列可以写成:
F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2) 对于 n > 1 的所有自然数 n。
斐波那契数列的前几个数是:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
这个数列在数学、科学、艺术和自然界中都有广泛的应用。例如,在生物学中,许多植物的生长模式(如菠萝的鳞片排列、向日葵的种子排列)遵循斐波那契数列。在艺术和设计中,黄金分割比例(Golden Ratio),也称为黄金比例(Golden Proportion),大约是1.618,这个比例与斐波那契数列紧密相关。
斐波那契数列的第n项可以通过递归、迭代或使用闭式公式(Binet’s Formula)来计算。闭式公式如下:
F(n) = (φ^n - (-φ)^-n) / sqrt(5)
其中,φ (phi) 是黄金比例,约等于1.618033988749895…,是(1 + sqrt(5)) / 2 的结果。这个公式可以直接计算出数列的任意一项,而不需要计算前面的所有项。
Java语言书写
在Java语言中,实现斐波那契数列可以通过多种方法,包括递归、迭代和使用矩阵快速幂。以下是这三种方法的详细实现:
- 递归方法:
递归方法是最直接的实现方式,但它的效率不高,因为会有很多重复的计算。
public class Fibonacci {public static int fibonacciRecursive(int n) {if (n <= 1) {return n;} else {return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);}}public static void main(String[] args) {int n = 10; // 计算前10项for (int i = 0; i < n; i++) {System.out.print(fibonacciRecursive(i) + " ");}}
}
- 迭代方法:
迭代方法效率更高,因为它避免了重复计算。
public class Fibonacci {public static int fibonacciIterative(int n) {if (n <= 1) {return n;}int fib = 1;int prevFib = 1;for (int i = 2; i < n; i++) {int temp = fib;fib += prevFib;prevFib = temp;}return fib;}public static void main(String[] args) {int n = 10; // 计算前10项for (int i = 0; i < n; i++) {System.out.print(fibonacciIterative(i) + " ");}}
}
- 矩阵快速幂方法(Binet’s Formula):
这种方法利用了斐波那契数列的闭式公式,通过矩阵乘法快速计算。
public class Fibonacci {public static int fibonacciMatrix(int n) {if (n == 0) {return 0;}int m = (int) Math.pow(5, 0.5);int[][] result = {{1, 1}, {1, 0}};int[][] base = {{1, 1}, {1, 0}};while (n > 0) {if (n % 2 == 1) {multiply(result, base, result);}multiply(base, base, base);n /= 2;}return result[0][0];}private static void multiply(int[][] a, int[][] b, int[][] result) {for (int i = 0; i < 2; i++) {for (int j = 0; j < 2; j++) {result[i][j] = 0;for (int k = 0; k < 2; k++) {result[i][j] += (long)a[i][k] * b[k][j] % m;}}}}public static void main(String[] args) {int n = 10; // 计算第10项System.out.println(fibonacciMatrix(n));}
}
在这个例子中,我们使用了黄金比例的平方根(m)来取模,以避免在计算过程中出现大数。这种方法的时间复杂度是O(log n),因为它基于二分法。
请注意,由于Java的整数类型(int)在处理大数时可能会溢出,所以在实际应用中,你可能需要使用long
类型或者Java的BigInteger
类来处理更大的斐波那契数。
需求场景:一个在线购物网站
一个在线购物网站想要在商品详情页面展示一个“推荐商品”区域,该区域会根据用户浏览的商品推荐相似的商品。为了实现这个功能,网站决定使用斐波那契数列来决定推荐商品的顺序,即推荐商品的顺序基于斐波那契数列的索引。例如,如果用户正在查看索引为5的商品(从0开始计数),那么推荐系统会推荐索引为3(F(3)=2)、2(F(2)=1)、1(F(1)=1)的商品。
解决步骤:
- 创建一个Java方法来生成斐波那契数列的前N项。
- 在商品详情页面的后端逻辑中,使用这个方法来获取推荐商品的索引。
- 根据这些索引从数据库中检索推荐商品并展示在页面上。
以下是实现这个需求的Java代码示例:
import java.util.ArrayList;
import java.util.List;public class FibonacciRecommendation {// 生成斐波那契数列的前N项public static List<Integer> generateFibonacci(int N) {List<Integer> fibonacciSeries = new ArrayList<>();int a = 0, b = 1, c = 0;// 初始化前两项fibonacciSeries.add(a);if (N > 1) {fibonacciSeries.add(b);}// 计算剩余的项for (int i = 2; i < N; i++) {c = a + b;fibonacciSeries.add(c);a = b;b = c;}return fibonacciSeries;}// 获取推荐商品的索引public static List<Integer> getRecommendedIndices(int currentProductIndex, int N) {List<Integer> recommendedIndices = new ArrayList<>();// 获取斐波那契数列List<Integer> fibonacciSeries = generateFibonacci(N);// 计算推荐商品的索引for (int index : fibonacciSeries) {if (index <= currentProductIndex) {recommendedIndices.add(currentProductIndex - index);}}return recommendedIndices;}// 主方法,用于测试public static void main(String[] args) {// 假设用户正在查看索引为5的商品int currentProductIndex = 5;int N = 10; // 推荐商品的数量// 获取推荐商品的索引List<Integer> indices = getRecommendedIndices(currentProductIndex, N);// 输出推荐商品的索引System.out.println("推荐商品的索引:" + indices);}
}
在这个例子中,generateFibonacci
方法用于生成斐波那契数列的前N项。getRecommendedIndices
方法接受当前商品的索引和推荐商品的数量N,然后返回一个推荐商品的索引列表。在main
方法中,我们测试了这个逻辑,假设用户正在查看索引为5的商品,并获取了推荐商品的索引。
请注意,这个例子是一个简化的版本,实际应用中可能需要考虑商品数据库的查询逻辑、用户偏好、商品的相似度等因素。此外,为了避免索引越界,实际应用中可能需要对推荐逻辑进行更复杂的处理。
需求:兔子问题(斐波那契数列)。
有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问第二十个月的兔子对数为多少?由此可见兔子对象的数据是:1 , 1 , 2 , 3 , 5 , 8 …
首先我们对其数据进行分析,可知从第三天开始,每天的兔子数量等于前两天之和,其次我们要知道递归的思想:
递归:在方法中调用方法本身的现象。注意事项:1.递归要有出口 2.递归次数不宜过多 3.递归所体现的思想,就是拆分合并的思想
public static void main(String[] args) {//定义一个方法去实现逻辑,传入月数并接收其返回值int sum = sumRabbit(20);//打印结果System.out.println("兔子的对数为:" + sum);}private static int sumRabbit(int i) {//判断传来的月数是不是第1个月或者两个月,如果是则返回1if (i == 1 || i == 2) {return 1;} else {//如果传来的月数不是1或者2,那么返回前两个月兔子数量的和;这里采用了递归的思想return sumRabbit(i - 1) + sumRabbit(i - 2);}}public class Demo5_2 {public static void main(String[] args) {System.out.println(fibonacci(5));}/*** 计算斐波那契数列 黄金分割线* @param month* @return*/public static int fibonacci(int month){
// 第一 1
// 第二 1
// 第三 2 第一月+ 第二月
// 第四月 3 第二月+ 第三月
// 第五月 5
// 第n月 ? 第n-1 + 第n-2
// 创建数组int[] arr = new int[month];arr[0] = 1;arr[1] = 1;for (int i = 2; i < arr.length; i++) {arr[i] = arr[i-1]+ arr[i-2];}System.out.println(Arrays.toString(arr));int sum = 0;for (int i = 0; i < arr.length; i++) {sum += arr[i];}return sum;}
}