项目欧拉#5效率和错误

时间:2015-11-13 21:31:33

标签: javascript

来自网站的问题:

2520是可以除以1到10之间的每个数字的最小数字,没有任何余数。

从1到20的所有数字均可被整除的最小正数是多少?

我的问题

我有一个问题,涉及我的代码中的效率和错误。当我无法通过自己的方式时,我已经研究并环顾了其他答案,但我仍然不明白如何实现这一目标。另外,当我用1-10插入2520时,我的代码显然不起作用。

请注意想要有关效率的答案或解决方案,只是解释我如何才能完成它( AKA暗示 EM>)。但是对于我的代码中的错误,我想要一个解决方案。在此先感谢您的帮助!

var recentArray = [];
var fullArray = [];
var numberCheck = 20;

function makeNewNumbers(i1, i2) {

    for (var i = i1; i < i2; i++) {
        recentArray = [];
        for (var j = 2; j <= numberCheck; j++) {
            recentArray.push(i % j);
        }
        fullArray.push(recentArray);
    }
}

var counter = 0;
var iStart = 0,
    iLess = 1000;
var success = false;

var newCheck = setInterval(function () {
    while (counter < 10 && success === false) {
        counter++;
        makeNewNumbers(iStart, iLess);
        for (var o = 1; o < fullArray.length; o++) {
            recentFound = false;
            if (numberCheck === 20 && fullArray[o][0] === 0 && fullArray[o][1] === 0 && fullArray[o][2] === 0 && fullArray[o][3] === 0 && fullArray[o][4] === 0 && fullArray[o][5] === 0 && fullArray[o][6] === 0 && fullArray[o][7] === 0 && fullArray[o][8] === 0 && fullArray[o][9] === 0 && fullArray[o][10] === 0 && fullArray[o][11] === 0 && fullArray[o][12] === 0 && fullArray[o][13] === 0 && fullArray[o][14] === 0 && fullArray[o][15] === 0 && fullArray[o][16] === 0 && fullArray[o][17] === 0 && fullArray[o][18] === 0) {
                clearInterval(newCheck);
                console.log("Success!!! Number: " + o);
                success = true;
                break;
            } else if (numberCheck === 10 && fullArray[o][0] === 0 && fullArray[o][1] === 0 && fullArray[o][2] === 0 && fullArray[o][3] === 0 && fullArray[o][4] === 0 && fullArray[o][5] === 0 && fullArray[o][6] === 0 && fullArray[o][7] === 0 && fullArray[o][8] === 0) {
                clearInterval(newCheck);
                console.log("Success!!! Number: " + o);
                success = true;
                break;
            }
        }
    }
    iStart += 1000;
    iLess += 1000;
    console.log("Not found...\nSearch is continued. To postpone type \'clearInterval(newCheck)\'\nNerd stats: --- Starting minimum: " + iStart + " --- Starting maximum: " + iLess);
}, 1);

3 个答案:

答案 0 :(得分:1)

以上算法有两个错误:

内部counter循环不会增加iStartiLess。因此,第二次迭代为1000th数组元素提供零i。这就是它给出答案1000的原因。应该在该循环中增加iStartiLess

while (counter < 10 && success === false) {
    // ...
    iStart += 1000;
    iLess += 1000;
}

在完整循环运行后,变量counter不会重置为零。因此,最大探测数为9999。在while循环counter应设置为零后。

这种算法效率很低。它能够解决10的问题。可能它可以用于15。但是,我不希望在合理的时间内收到20的结果。

更高效和非常明显的算法可能基于计算给定范围(1..20)内所有数字的素因子。应该将范围内所有数字的每个唯一素因子的最大计数相乘以得到结果。 使用欧几里得算法可以做得更好。

答案 1 :(得分:1)

当解决这样的问题时,可以简化问题的本质。通过它会更容易。例如,解决这个更简单的问题:

12是可以除以1至4中的每个数字而没有任何余数的最小数字。

如果需要,首先使用笔和纸以及伪代码进行编码。

使用%remainder运算符时,还要检查没有余数,并保持运行计数。您似乎将结果存储在一个不必要的数组中。

另一个提示 - 你要求我们不评论效率,但这是问题的标题。

由于这是一个欧拉问题,即使是一个增加20并且依次检查其他数字的强力算法,对欧几里得方法的快速了解也是不必要的。它只需要答案而不是有效的方法。

对于更大数量的效率要求和数字溢出&#39;检查都需要考虑。

答案 2 :(得分:1)

使用数学,而不是暴力。

  

从1到20的所有数字均可被整除的最小正数是多少?

在数学上,这被称为least common multiple的1,...,20。

计算两个数字的最小公倍数的一种非常快速的方法是使用Euclidean algorithm来计算greatest common divisor

function gcd(a, b) { // Greatest common divisor
  if(b == 0) return a;
  return gcd(b, a%b);
}
function lcm(a, b) { // Least common multiple
  return a * b / gcd(a, b);
}
var n = 1;
for(var i=1; i<=20; ++i) n = lcm(n, i);
n; // 232792560