Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/253.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
优化PHP算法_Php_Algorithm - Fatal编程技术网

优化PHP算法

优化PHP算法,php,algorithm,Php,Algorithm,我已经建立了一个类,它可以找到一个给定范围内的所有数都可以整除的最小数 这是我的代码: class SmallestDivisible { private $dividers = array(); public function findSmallestDivisible($counter) { $this->dividers = range(10, 20); for($x=1; $x<$counter; $x++) {

我已经建立了一个类,它可以找到一个给定范围内的所有数都可以整除的最小数

这是我的代码:

class SmallestDivisible
{

    private $dividers = array();

    public function findSmallestDivisible($counter)
    {
        $this->dividers = range(10, 20);

        for($x=1; $x<$counter; $x++) {

            if ($this->testIfDevisibleByAll($x, $this->dividers) == true) {
                return $x;
            }
        }
    }

    private function testIfDevisibleByAll($x, $dividers)
    {
        foreach($dividers as $divider) {
            if ($x % $divider !== 0) {
                return false;
            }
        }

        return true;
    }
}

$n = new SmallestDivisible();

echo $n->findSmallestDivisible(1000000000);
类最小可除
{
私有$dividers=array();
公共函数findSalestDivisible($counter)
{
$this->dividers=范围(10,20);
对于($x=1;$XTEStifDesibleByall($x,$this->dividers)==true){
返回$x;
}
}
}
私有函数testifdevicibyAll($x,$dividers)
{
foreach($dividers作为$divider){
如果($x%$divider!==0){
返回false;
}
}
返回true;
}
}
$n=新的最小可除数();
echo$n->FindSalestDivisible(100000000);
此类查找可被1到20范围内的所有数字整除的数字(
$This->dividers

我知道它工作得很好,因为我用其他较低的范围对它进行了测试,但不幸的是,它无法在30秒内找到
range(10,20)
的解决方案,而这正是PHP脚本停止的时间

馈送到
findsmalestdivisible
方法的参数是脚本要检查的数字组的上限(即从1到
$counter
(100000000是此执行))


如果您能就如何优化此脚本以使其执行更快提出建议,我将不胜感激。

您的解决方案是蛮力和可怕的

相反,用数学方法来处理它怎么样?您正在寻找范围内最低的常用数字倍数,因此

function gcd($n, $m) {
   $n=abs($n); $m=abs($m);
   list($n,$m) = array(min($m,$n),max($m,$n));
   while($r = $m % $n) {
      list($m,$n) = array($n,$r);
   }
   return $n;
}
function lcm($n, $m) {
   return $m * ($n/gcd($n,$m));
}

function lcm_array($arr) {
   while(count($arr) > 1) {
      array_push($arr, lcm(array_shift($arr),array_shift($arr)));
   }
   return array_shift($arr);
}

var_dump(lcm_array(range(10,20)));
// result int(232792560)

这意味着您的原始代码必须进行232792560次迭代,难怪要花这么长时间

你的解决方案是蛮力,简直太可怕了

相反,用数学方法来处理它怎么样?您正在寻找范围内最低的常用数字倍数,因此

function gcd($n, $m) {
   $n=abs($n); $m=abs($m);
   list($n,$m) = array(min($m,$n),max($m,$n));
   while($r = $m % $n) {
      list($m,$n) = array($n,$r);
   }
   return $n;
}
function lcm($n, $m) {
   return $m * ($n/gcd($n,$m));
}

function lcm_array($arr) {
   while(count($arr) > 1) {
      array_push($arr, lcm(array_shift($arr),array_shift($arr)));
   }
   return array_shift($arr);
}

var_dump(lcm_array(range(10,20)));
// result int(232792560)

这意味着您的原始代码必须进行232792560次迭代,难怪要花这么长时间

您的目标是一个简单的数学计算,名为,但使用蛮力计算是完全错误的(正如您已经发现的)

下面列出了几个合理的算法,可以用来加快计算速度


在“”一节中解释的一个非常快,不需要太多内存。您只保留表中最左边的一列(您想要获取的
lcm
的数字)和最右边的一列(当前步骤)。如果你实现了它,我建议你将一个列表硬编码到你的程序中,以避免计算它们。

你的目标是一个简单的数学计算,但使用蛮力来计算它是完全错误的(正如你已经发现的)

下面列出了几个合理的算法,可以用来加快计算速度


在“”一节中解释的一个非常快,不需要太多内存。您只保留表中最左边的一列(您想要获取的
lcm
的数字)和最右边的一列(当前步骤)。如果您实现了它,我建议您将一个列表硬编码到您的程序中,以避免计算它们。

这里是我提出的另一个解决方案

简言之,该算法将计算一组数字的LCM(lesast公共倍数)

class Lcmx
{

    public $currentLcm = 0;

    private function gcd($a, $b)
    {
        if ($a == 0 || $b == 0)
            return abs( max(abs($a), abs($b)) );

        $r = $a % $b;
        return ($r != 0) ?
            $this->gcd($b, $r) :
            abs($b);
    }   

    private function lcm($a, $b)
    {
        return array_product(array($a, $b)) / $this->gcd($a, $b);
    }

    public function lcm_array($array = array())
    {
        $factors = $array;  
        while(count($factors) > 1) {

            $this->currentLcm = $this->lcm(array_pop($factors), array_pop($factors));
            array_push($factors, $this->currentLcm);
        }

        return $this;

    }
}

$l = new Lcmx;
echo $l->lcm_array(range(1, 20))->currentLcm;
//232792560

这是我想出的另一个解决办法

简言之,该算法将计算一组数字的LCM(lesast公共倍数)

class Lcmx
{

    public $currentLcm = 0;

    private function gcd($a, $b)
    {
        if ($a == 0 || $b == 0)
            return abs( max(abs($a), abs($b)) );

        $r = $a % $b;
        return ($r != 0) ?
            $this->gcd($b, $r) :
            abs($b);
    }   

    private function lcm($a, $b)
    {
        return array_product(array($a, $b)) / $this->gcd($a, $b);
    }

    public function lcm_array($array = array())
    {
        $factors = $array;  
        while(count($factors) > 1) {

            $this->currentLcm = $this->lcm(array_pop($factors), array_pop($factors));
            array_push($factors, $this->currentLcm);
        }

        return $this;

    }
}

$l = new Lcmx;
echo $l->lcm_array(range(1, 20))->currentLcm;
//232792560

现在需要多长时间?你想让它花多长时间?考虑对工作代码提出优化问题(也就是PHP脚本停止的时间)。Kjjro,我真的希望脚本在30秒的时限内执行。“安迪,我只知道脚本在30秒内找不到想要的号码。现在需要多长时间?”你想让它花多长时间?考虑对工作代码提出优化问题(也就是PHP脚本停止的时间)。Kjjro,我真的希望脚本在30秒的时间限制内执行。“安迪,我只知道脚本在30秒内找不到想要的号码。这肯定是要走的路。我真的需要练习我的数学思维能力。我倾向于为我遇到的问题编写暴力算法。他们经常工作,但他们不是我想写下我的名字:)谢谢@niet,你能不能解释一下你的代码在每一步中都做了些什么?也许是以代码内注释的形式?这肯定是一条路要走。我真的需要练习我的数学思维能力。我倾向于为我遇到的问题编写暴力算法。他们经常工作,但他们不是我想写下我的名字:)谢谢@niet,你能解释一下你的代码在每一步中都做了什么吗?也许是以代码内注释的形式?