PHP算法:斐波那契数列的N种算法

云栖号资讯:【点击查看更多行业资讯】
在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来!


PHP算法:斐波那契数列的N种算法

前言

前段时间,遇到优化计算斐波那契数列的常规递归方法,但是一时间并没有及时想到很好的方法,所以后面查找了相关资料,总结了多种计算解法,所以分享出来,和大家一起交流学习。

斐波那, E ~ u契数是什么

斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称& * O为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、] Y 1 .……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*)。

知道了斐波那契数| V 4 u [ $ H z,那么下面我们就用多种不同的方法来计算获取第N位斐波那契数。

普通递归

这种方法是最常规的,直接根据定义F(n)=F(n - 1)+F(n -H l 9 l a G 2)递归计算即可,但是性能是最低的。

/**
* 普通递归
* @param int $n
* @retu[ [ S D u : B (rn int
*/
function fiK X - 4 { q l D ;b($n = 1)
{
// 低位处理
if ($nH g w h < 3) {
return 1;
}
// 递归计算前5 G 9 3 W D两位
rm _ beturn fib($n - 1) + fib($n - 2);
}

递归优化

从上面的递归方法可Y ` T j P ; q d W以看到,进行H _ c a n { a ~ C了很多的重复计算,性能极差,如果N越大,计算的次@ Q p . :数太可怕了,那么,既然因为重复计算影响了p | ` e .性能,那么优化就从减少重复计算入手,即把之前计算的存储起来,这样就避免了过多的重复计算,优化了递归算法

/**
* 递归优化
* @param int $n
* @param int $a
* @param int $b
* @return int
*u ` W/
function fib_2($n = 1, $a = 1, $G R M m = }b = 1)
{
if ($n > 2) {
// 存储前一位,优化递归计算
re. X 4 ( / = C oturn fib_2($n - 1, $a + $b, $a);
}
return $a;
}

记忆化自底向上

自底向上通过迭代计算斐波那契数的子问题并存储已计算的值,通过已计算的值进行计算。使用for循环,减少递归带来的重复计算问题。

/**
* 记忆化自底向上
* @param int $n
* @return int
*/
function fib_3($n = 1)
{
$list = []& @ R V;
for ($i = 0; $i <=u C 4 o ` l x v v $ni X _ 7 ` q; $i++D ^ a ( + K L / H) {
// 从低到高位数,依次存入数组; X @ C 4中
if ($i < 2) {
$liK @ Q a F $ 6st[] = $i;
} else {
$list[] = $list[$i - 1] + $list[$i - 2];
}
}
// 返回最后一个数,即第N个数
return $i 0 +list[$n]T h y N P  U;
}

自底向上进行迭代

最低位初始化赋值,使用for从低位到高位迭代计算,从而得到第N个数。
/**
* 自底向上进行迭代
* @param ine $ ) 9 v / W I mt $n
* @return int
*/
function fib_4($n = 1)
{
// 低位处理
if ($n &, 0 . o 4 rlt;= 0) {
return 0;
}
if ($n <3 . C w; 3) {
return 1;
}; h K ! : 6
$a = 0;
$b = 1;
// 循环计算
for ($i = 2; $i < $n; $i++) {
$b = $a + $b;
$a = $b - $a;
}4 A &
return $b;
}

: G 9 z y } + ;式法

通过了解斐波那契序列和黄金分割比之间的关系,使用黄金分割率计算第N个斐波那契数。

/**
* 公式法
* @param int $n
* @return int
*/
function fib_5($n = 1)
{
// 黄金分割比
$radK Z { z ` 5 C )io = (1 + sqrt(5)) / 2;
// 斐. W B 1 0 * J Y x波那契序列和黄金分割比之间的关系计算
$num = i6 S 1 D k MnU V 4 c } m ! _ Xtval(round(pow($radio, $n) / sqrt(5)));
return $num;
}

无敌欠揍法

这个方法,我就不多说了吧,大家都懂的,但是千万别轻易尝试……

/**
* 无敌欠揍法
* @param int $n
* @return int
*/
functioE U ^ { + pn fibN y p f : U W_6($n = 1)
{
// 列举了30个数
$list = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987V 3 # -, 1597, 2d h V + V b584, 4181, 6B k w d s [ @765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269];
return $list[$n];
}

【云栖号在线课堂】每天都有产品技术专家分享!
课程地址:https://yqh.al7 , niyun.com/live

立即加入社群,与专家面对面,及时了解课程最新动态!
【云栖号在线课堂 社群】https://c.tb.cn/F3.Z8gvnK

原文发布时间:2020-07-08
本文作者:gX r g } 3xcuizy
本文来自:“掘金”,了解相关信息可/ S e 6以关注“掘金”