如何优化该算法

时间:2014-03-08 05:36:40

标签: php algorithm

我正在尝试找到可被1到20之间的所有数字整除的最小正数,这是代码:

$num = 2520;
$x = 1;

while($x < 21){
    if($num % $x == 0){
        $x++;
    }else{
        $num += 20;
        $x = 1;
    }
}

echo $num;

它在不到1分钟的时间内提供了正确的输出。这个执行时间在专业领域是不是很糟糕?有什么办法优化这个?

P.S。我从2520开始,因为它是可以除以1到10之间的每个数字的最小数字,没有任何余数。

3 个答案:

答案 0 :(得分:1)

建议:在[1,20]中找到所有整数的素数。

例如,我们有素数{2,3,5,7,11,13,17,19}。所以,如果解决方案是可分的 通过[1,20]中的所有整数,当然它可以被这个中的每个元素整除 素数列表。所以,至少,我们的解决方案是&gt; = 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19,对吧?

现在的问题是我们如何聪明地构建候选解决方案 大于那个数字。好吧,让我们先看看有多少解决方案已经完成......

2 * 3 * 5 * 7 * 11 * 13 * 17 * 19可被4整除吗?不,所以,让我们多来2来得到 2 * 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19,一定可以被2 * 2整除......

2 * 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19可以被6整除吗?是。

2 * 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19可被8整除吗? ....

你得到了照片。虽然我不确定,但我相信这种方法会 得到正确的答案 - 即每个可被整除的最小整数 [1,20]中的整数。

答案 1 :(得分:0)

这听起来像Project Euler's Problem 5

我们在这里找到的是数字1到20的least common multiple。您可以在greatest common divisor的帮助下找到它:

function gcd($a, $b) {
    if ($a == 0) return $b;
    return gcd($b % $a, $a);
}

function lcm($a, $b) {
    return $a * $b / gcd($a, $b);
}

function smallestDiv($n) {
    $div = 1;
    for ($i = 1; $i <= $n; $i++) {
        $div = lcm($div, $i);
    }
    return $div;
}

echo smallestDiv(20);

原谅我的PHP。自从我写完以来已经有一段时间了。

请注意,我们也可以通过每个数字的素数分解找到答案,并查找hereKode Charlie's中所述的最大指数:

 2 = 2
 3 = 3
 4 = 2²
 5 = 5
 6 = 2 × 3
 7 = 7
 8 = 2³
 9 = 3²
10 = 2 × 5
11 = 11
12 = 2² × 3
13 = 13
14 = 2 × 7
15 = 3 × 5
16 = 2⁴
17 = 17
18 = 2 × 3²
19 = 19
20 = 2² × 5

lcm(1,2,…20) = 2⁴ × 3² × 5 × 7 × 11 × 13 × 17 × 19 = 232,792,560

答案 2 :(得分:0)

使用改良的Eratosthenes筛子进行大规模加速

1.int ix [20] = {1,2,3,4,... 20};

2.现在写一个循环

  • 你将增加所有ix [i] + = i + 1;其中i =&lt; 0; 18&gt;
  • 而ix [i]&gt; = ix [19]
  • 如果最后所有ix [i]都是相同的那么它的竞争是结果所以停止/返回任何

3.如果没有那么增量也是ix [19] + = 20;

  • 并继续使用bullet 2
  • 上的循环

[注释]

  • 可以很容易地改变,因为任何不仅可以被1..20
  • 整除的数字都可以整除