这是针对Project Euler,问题#5。
任务是找到可被1-8号整除的最小数字。我的代码似乎在1-18工作,但在19我的浏览器开始超时。这让我相信我的代码效率低下。
我该如何缓解这种情况?
function divisible(a){
counter = 0;
result = 2;
while (counter < a){
for (var x = 0; x <= a; x ++){
if (result % x === 0){
counter ++;
}
}
if (counter != a){
counter = 0;
result ++;
}
}
return result;
}
divisible(20)
答案 0 :(得分:1)
是的,效率低下。您需要更改算法。我能想到的最有效的方法是将所有数字从2到20分解(有因子和计数:例如18是3 * 3 * 2,或者两次3和一次2,对于最终{ 3: 2, 2: 1 }
);然后找出每个因子的最大值,并将它们相乘。
一个缩写示例:可被18和16整除的最小数字:
18: { 3: 2, 2: 1 }
16: { 2: 4 }
maximums of factor repetitions: { 3: 2, 2: 4 }
result: 3^2 * 2^4 = 144
从2到20的因子分解很容易;如果您不知道如何操作,有许多可能的算法,您可以看到the Wikipedia article on integer factorisation的想法。
答案 1 :(得分:1)
基本上,您希望least common multiple为1,...,20。
我会使用gcd
来实现lcm
,这可以使用快速Euclidean algorithm来实现。
function gcd(a, b) {
return b === 0 ? a : gcd(b, a%b); // Euclidean algorithm
}
function lcm(a, b) {
return a * b / gcd(a, b);
}
function divisible(a){
var result = 1;
for(var i=2; i<=a; ++i)
result = lcm(result, i);
return result;
}
divisible(20); // 232792560
答案 2 :(得分:1)
另一种选择蛮力和模数休息分类
这个问题可以用一个简单的模数休息类特征来解决。 查看1到20之间的数字,并将其分为两组,并在它们之间找到一些独特的共同属性。
1 2 3 4 5 6 7 8 9 10
we are building a division with the same reminder members
1除以所有
2划分4,8 - &gt;&gt; 8重要
3除以6,9但6不均匀地划分9 - &gt; 6,9
5划分10 - &gt;&gt; 10重要
让我们留下6,7,8,9,10来检查1中是否有任何数字可以将其与休息0分开。
诀窍是如果2,4,8除了一个数字,让16说同一个提醒,那么我们不必检查2,4分16,我们只检查8。
11 12 13 14 15 16 17 18 19 20
这里我们可以从上面的数字因素中做同样的事情,我们将留下
11 12 13 14 15 16 17 18 19 20
注意:我们知道必须除以数字的最后一个数字是20, 所以这意味着解决方案将是一个以0结尾的数字或者是 其中一个因素是20,所以我们建立20的因子并检查是否11 12 13 14 15 16 17 18 19可以分割它然后我们就完成了。
int start = 20;
while (start % 11 != 0 || start % 12 != 0 | start % 13 != 0 || start % 14 != 0 ||
start % 15 != 0 || start % 16 != 0 || start % 17 != 0 || start % 18 != 0 || start % 19 != 0 )
{
start += 20;
}
console.log(start)
同样的想法适用于我做的第一次演绎 问题似乎更小。
//最小数字可被1到10之间的所有数字整除
int a = 10;
while (a % 6 != 0 || a % 7 != 0 | a % 8 != 0 || a % 9 != 0 )
{
a += 10;
}
console.log(a)
//最小数字可被1到5之间的所有数字整除
int i = 5;
while (i % 3 != 0 || i % 4 != 0)
{
i += 5;
}
console.log(i)