优化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,你能解释一下你的代码在每一步中都做了什么吗?也许是以代码内注释的形式?