by emanjusaka from https://www.emanjusaka.top/archives/9 彼岸花开可奈何
本文欢迎分享与聚合,全文转载请留下原文地址。
斐波那契数列在代码中的应用是比较常见的,下面让我们来了解下一个数学上的数列在代码中会有哪些应用。了解斐波那契,可以给我们提供解决某些问题的思路,优化解决问题的方法。
F0 = 0,F1 = 1,Fn = F(n - 1) + F(n - 2)
F0 | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | F13 | F14 | F15 | F16 | F17 | F18 | F19 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 55 | 89 | 144 | 233 | 377 | 610 | 987 | 1597 | 2584 | 4181 |
public double fibonacci(int n) {
int f1 = 1;
int f0 = 0;
if (n < 2) return n;
int num = n - 1;
while (num > 0) {
f1 += f0;
f0 = f1 - f0;
num --;
}
return f1;
}
public int fibonacciRecursion(int n) {
if (n < 2){
return n;
} else {
return (fibonacciRecursion(n - 1) + fibonacciRecursion(n - 2));
}
}
public double fibonacciClosedForm(long position) {
int maxPosition = 75;
if (position < 1 || position > maxPosition) {
throw new RuntimeException("Can't handle position smaller than 1 or greater than 75");
}
double sqrt = Math.sqrt(5);
double phi = (1 + sqrt) / 2;
return Math.floor((Math.pow(phi, position)) / sqrt + 0.5);
}
在用来设计散列函数的除法散列法中,通过取 K 除以 M 的余数,将关键字 K 映射到 M 个槽中的某一个位置上,即散列函数为:h(K) = K mod M 表格大小通常是 2 的幂。
另外除法散列的一个显着缺点是除法在大多数现代架构(包括 x86)上都是微编程的,并且可能比乘法慢 10 倍。
乘法散列法整体包含两步:
A(0<A<1)
,并去除kA的小数部分floor
公式:h(K)=Math.floor[m(aK mod 1)]
步骤:
(k<2wk<2w)
[0,2w]
内的任意数值 ss,k×sk×s 即可用R1·2w+R0R1·2w+R0
来表示(k·A)mod1=k·s/2w(k·A)mod1=k·s/2w
就是将k×sk×s
整体向右平移 ww 位,此时R0R0即为小数部分h(k)h(k)
为 R0R0 的前 m 位。乘法散列只需要单个整数乘法和右移,使其成为计算速度最快的哈希函数之一。但乘法散列可能会在变更计算因子后,较高值的输入位不会影响较低值的输出位,问题体现在元素分散不均,不满足严格的雪崩标准。所以通常在会进行异或操作
乘法散列容易受到导致扩散不良的“常见错误”的影响——较高值的输入位不会影响较低值的输出位。在乘法步骤对此进行校正之前,输入上的变换将保留的最高位的跨度向下移动,并将它们异或或加到键上。所以在输入上的变换将保留的最高位的跨度向下移动,并将它们异或操作或者加到键上。例如 HashMap 的扰动函数。
其实斐波那契散列是一种特殊形式的乘法散列,只不过它的乘法因子选择的是一个黄金分割比例值,所以叫做斐波那契散列。
斐波那契散列的特性在于将“大数映射到小数”的计算结果在表空间上是均匀分布的,且计算满足乘法散列效率高。
斐波那契数列可以用于生成伪随机数序列。虽然斐波那契数列本身不是真正的随机数序列,但通过适当的变换和截取,可以得到具有一定随机性的序列。
package top.emanjusaka;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
System.out.println(fibonacciRandom(5, 8));
}
public static List<Integer> fibonacciRandom(int seed, int length) {
List<Integer> fibSequence = new ArrayList<>(Arrays.asList(0, 1));
while (fibSequence.size() < seed + length) {
int nextNumber = fibSequence.get(fibSequence.size() - 1) + fibSequence.get(fibSequence.size() - 2);
fibSequence.add(nextNumber);
}
List<Integer> randomSequence = new ArrayList<>();
for (int i = seed; i < seed + length; i++) {
randomSequence.add(fibSequence.get(i));
}
return randomSequence;
}
}
在AVL树中,斐波那契数列可以用于平衡因子的调整和旋转操作。
AVL树是一种自平衡二叉搜索树,它要求左右子树的高度差不超过1,以保持树的平衡性。当对AVL树进行插入或删除操作时,可能会破坏树的平衡,这时需要对树进行旋转操作来恢复平衡。
在AVL树的旋转操作中,涉及到更新节点的高度信息。通常,节点的高度可以通过其子节点的高度来计算。而斐波那契数列正好提供了方便的计算方式。
具体应用如下:
斐波那契数列在最大公约数计算中有一个有趣的应用,称为"连续整除性质"。
假设我们有两个正整数a和b,并且a > b。如果a可以被b整除,那么a与斐波那契数列中位于第a个位置(从1开始计数)的数具有相同的最大公约数。换句话说,gcd(a, b) = gcd(b, F(a)),其中F(n)表示斐波那契数列中第n个数。
这个性质的证明基于斐波那契数列的递推关系和欧几里得算法的原理。简单来说,当a能够被b整除时,可以将a表达为b的倍数加上剩余部分,即a = qb + r,其中q是商,r是余数。然后我们可以使用斐波那契数列的递推关系,即F(n) = F(n-1) + F(n-2),将a和b替换为它们的等价表达式:
gcd(a, b) = gcd(qb + r, b) = gcd(b, r)
这就意味着最初的问题可以转化为更小的问题,即求b和r的最大公约数。通过重复应用这个性质,我们最终可以将问题简化为求最小的b和斐波那契数列中的一个数之间的最大公约数。
这个连续整除性质可以用于计算任意两个正整数的最大公约数,而不需要直接使用辗转相除法。通过与斐波那契数列相关联,它提供了一种更高效的方法来计算最大公约数。
需要注意的是,连续整除性质只适用于a > b的情况,因此在应用时需要确保a和b的大小顺序。
在合并排序算法中,斐波那契数列可以用于确定合并的子数组大小。
合并排序是一种基于分治思想的排序算法,它将待排序的数组不断地拆分为较小的子数组,并对这些子数组进行排序,然后再将排好序的子数组合并为一个有序数组。斐波那契数列在确定子数组大小时可以发挥作用。
具体应用如下:
斐波那契数列在合并排序算法中的应用,主要是为了确定子数组的大小,以实现更灵活和高效的排序过程。利用斐波那契数列的特性,可以使合并排序算法更加平衡、快速和优化。
本文原创,才疏学浅,如有纰漏,欢迎指正。如果本文对您有所帮助,欢迎点赞,并期待您的反馈交流,共同成长。
原文地址: https://www.emanjusaka.top/archives/9
微信公众号:emanjusaka的编程栈