在php中记忆Fibonacci函数

vx6bjr1n  于 2023-01-08  发布在  PHP
关注(0)|答案(5)|浏览(149)

我已经创建了一个递归形式的fibonacci的记忆函数,我用它作为其他类型的函数使用记忆的例子,我的实现是糟糕的,因为如果我把它包含在一个库中,这意味着global变量仍然可见。
这是原始的递归斐波那契函数:

function fibonacci($n) {
  if($n > 1) {
    return fibonacci($n-1) + fibonacci($n-2);
  }
  return $n;
}

我把它修改成了一个记忆版本

$memo = array();
function fibonacciMemo($n) {
  global $memo;
  if(array_key_exists($n, $memo)) {
    return $memo[$n];
  }
  else {
    if($n > 1) {
      $result = fibonacciMemo($n-1) + fibonacciMemo($n-2);
      $memo[$n] = $result;
      return $result;
    }
    return $n;
  }
}

我故意没有使用迭代法来实现斐波那契。有没有更好的方法来记忆斐波那契函数?你能给我建议更好的改进吗?我已经看到了func_get_args()call_user_func_array作为另一种方法,但我似乎不知道什么是更好的?
所以我的主要问题是:* * 如何在php中正确记忆斐波那契函数?在php中记忆斐波那契函数的最佳方法是什么?**

neekobn8

neekobn81#

EddMann展示了一个在His post中用php实现memoize函数的好方法
下面是示例代码(实际上摘自Edd Mann的帖子):

$memoize = function($func)
{
    return function() use ($func)
    {
        static $cache = [];

        $args = func_get_args();

        $key = md5(serialize($args));

        if ( ! isset($cache[$key])) {
            $cache[$key] = call_user_func_array($func, $args);
        }

        return $cache[$key];
    };
};

$fibonacci = $memoize(function($n) use (&$fibonacci)
{
    return ($n < 2) ? $n : $fibonacci($n - 1) + $fibonacci($n - 2);
});

注意,由于函数clousure和PHP的一流函数支持,global定义被替换了。

其他解决方案:

您可以创建一个class,其中包含以下静态成员:fibonnacciMemo$memo。请注意,您不再需要将$memo用作全局变量,因此它不会与其他名称空间给予任何冲突。

class Fib{
    //$memo and fibonacciMemo are static members
    static $memo = array();
    static function fibonacciMemo($n) {
      if(array_key_exists($n, static::$memo)) {
        return static::$memo[$n];
      }
      else {
        if($n > 1) {
          $result = static::fibonacciMemo($n-1) + static::fibonacciMemo($n-2);
          static::$memo[$n] = $result;
          return $result;
        }
        return $n;
      }
    }
}

//Using the same method by Edd Mann to benchmark 
//the results

$start = microtime(true);
Fib::fibonacciMemo(10);
echo sprintf("%f\n", microtime(true) - $start);
//outputs 0.000249

$start = microtime(true);
Fib::fibonacciMemo(10);
echo sprintf("%f\n", microtime(true) - $start);
//outputs 0.000016 (now with memoized fibonacci)

//Cleaning $memo
Fib::$memo = array();
$start = microtime(true);
Fib::fibonacciMemo(10);
echo sprintf("%f\n", microtime(true) - $start);
//outputs 0.000203 (after 'cleaning' $memo)

使用这个,你可以避免使用global,也可以避免 * 清理该高速缓存 * 的问题。尽管$memo不是 * 线程保存 *,存储的键也不是 * 散列值 *。无论如何,你可以使用所有的php memoize实用程序,比如memoize-php

js5cn81o

js5cn81o2#

我想......这应该是为了记住斐波那契:

function fib($n, &$computed = array(0,1)) {
    if (!array_key_exists($n,$computed)) {
        $computed[$n] = fib($n-1, $computed) + fib($n-2, $computed);   
    }
    return $computed[$n];
}

一些测试

$arr =  array(0,1);
$start = microtime(true);
fib(10,$arr);
echo sprintf("%f\n", microtime(true) - $start);
//0.000068

$start = microtime(true);
fib(10,$arr);
echo sprintf("%f\n", microtime(true) - $start);
//0.000005

//Cleaning $arr
$arr =  array(0,1);
$start = microtime(true);
fib(10,$arr);
echo sprintf("%f\n", microtime(true) - $start);
//0.000039
mzaanser

mzaanser3#

另一种解决方案:

function fib($n, &$memo = []) {

    if (array_key_exists($n,$memo)) {
        return $memo[$n];
    }

    if ($n <=2 ){
        return 1;
    }

    $memo[$n] = fib($n-1, $memo) + fib($n-2, $memo);

    return $memo[$n];
}

性能:

$start = microtime(true);
fib(100);
echo sprintf("%f\n", microtime(true) - $start);
// 0.000041
7hiiyaii

7hiiyaii4#

这是一个记忆斐波那契数列的实现:

function fib(int $n, array &$memo = [0,1,1]) {

    return $memo[$n] ??  $memo[$n] = fib($n-1, $memo) + fib($n-2, $memo);

}

呼叫

echo fib(20); // 6765
ni65a41a

ni65a41a5#

function fibMemo($n)
            {

                static $cache = [];
                //print_r($cache);
                if (!empty($cache[$n])) {
                    return $cache[$n];
                } else {
                    if ($n < 2) {
                        return $n;
                    } else {
                        $p   = fibMemo($n - 1) + fibMemo($n - 2);
                        $cache[$n]  = $p;
                        return $p;
                    }
                }
            }
            echo fibMemo(250);

相关问题