【问题标题】:How to calculate LCM for natural numbers 1 to N in Javascript?如何在Javascript中计算自然数1到N的LCM?
【发布时间】:2015-07-30 23:18:45
【问题描述】:

所以,我的问题是找到从 1 到 20 的所有数字的最小倍数。我确实成功地解决了这个任务,但我的程序运行得相当慢。这是代码,我使用的 n 的最终数字是 1 亿。 可以想象,这需要很多时间。所以我想知道,我将如何优化这段代码? 此外,很高兴知道如何更改它应该分成的数字的数量,所以不是 1 到 20,而是 1 到 15。

function smallestMultiple(n) {
    for (i = 0; i< n; i++) {
        if (i%1 === 0 && i%2 === 0 && i%3 === 0 && i%4 === 0 && i%5 === 0 
                 && i%6 === 0 && i%7 === 0 && i%8 === 0 && i%9 === 0 
                 && i%10 === 0 && i%11 === 0 && i%12 === 0 && i%13 === 0 
                 && i%14 === 0 && i%15 === 0 && i%16 === 0 && i%17 === 0 
                 && i%18 === 0 && i%19 === 0 && i%20 === 0 ) {

            console.log(i);
        }
    };
};

现在,很明显,这需要 5 多分钟才能找到答案。我想知道是否有更有效的方法? 编辑:显然我也可以使用 1-20 的变量。将对此进行调查,如果您有答案,请彻底解释您的答案以及为什么它更有效。

【问题讨论】:

  • lcm(1, lcm(2, lcm(3, ...))),其中lcm 是最小公倍数。
  • 取你的最大数(在本例中为 20)并像这样更改你的 for:for (i = 0; i&lt; n; i +=20 )
  • 当你找到第一个成功的号码时,你应该跳出for循环。
  • 您不必检查任何非质数的模数 - %18 是多余的,因为当 i%9 == 0 我们已经知道 i%(9*2) == 0
  • 您无需针对所有相互为倍数的数字进行测试。如果n 是 20 的倍数,那么它也是其所有因数的倍数,因此您无需测试 2、4、5 和 10。

标签: javascript algorithm modulo


【解决方案1】:

我想我直接从论坛中找到了最优雅的解决方案之一:

没有实际尝试过,我想象一些“蛮力” 这里的方法违反了“1分钟规则”。然而,考虑到一个 微小的变化可以大大提高算法的效率。

假设“蛮力”方法是:迭代每个自然 number - 如果电流可以被每个数字整除 1 到 20 岁,你已经找到了答案。

考虑一下:如果你知道 N 的解是 X,那么 N+1 的解必须能被 X 整除。因此,当迭代 通过自然数,您可以通过 X 而不是 1 进行迭代。并且 而不是检查数字 1 到 N+1 的可分性,你 只需检查 N+1,因为您已经知道值 (X 的倍数) 都可以被 1 整除到 N。

举个例子,假设 10 的答案是 2520,得到 11 的解,我们检查 2520 是否能被 11 整除。不是, 我们迭代到 5040 并检查它是否能被 11 整除。我们继续 直到我们发现 27720 可以被 11 整除,这就是答案。

尽管没有尝试直接确定 LCD,但最终结果是 是一个相当快速的算法,可以在一秒钟内轻松运行 N 值稍大。

在 Ruby 中(尽管类似的方法可用于许多高级 语言):

def snd(max) result = 1 for n in 1..max 上一页 = 结果 结果 % n > 0 结果 += 上一个 end end 返回结果 end

放snd(20)

然后我将其解释为 Javascript 并得到了这个脚本

console.log("Please type in smallestMultiple(n), whereas n is the smallest multiple.");

function smallestMultiple(n) {
   var result = 1;
   var prev;
   for (i=1; i<n+1; i++) {
       prev = result;
       while (result%i > 0) {
           result += prev;
       }
   }
   console.log(result);
};
&lt;script src="https://getfirebug.com/firebug-lite-debug.js"&gt;&lt;/script&gt;

编辑:在将返回 smallestNumber(11) = 2520 的脚本中发现错误。已在 for 循环中修复:for(i=0; in+1 ;i++)

【讨论】:

  • 现在 this 很优雅。
  • 这太棒了。当您越接近答案时,它的速度就会呈指数级增长。
  • smallestMultiple(11) == 2520, 2520/11 == 229.0909090909091?
  • 我可以补充一下,因为你已经有了 n(11)= 27720,你不再需要 n(10),因为你知道所有以前的数字都是可整除的。所以你迭代 n(11) 直到你发现 n(13) 的最小倍数仍然是 27720,但 n(14) 不是。因此,将 n(13) + n(13) 相加,得到 55440、73160...等。直到达到 360360,这确实是 14 的 LCM。
  • @dave 如您所见,我已修复它。现在它可以工作了。如果出现任何其他错误,请告诉我。
【解决方案2】:

使用reduction by the greatest common divisor的方法

跳过数字 1 - 10,因为您可以将其中任何一个乘以 2 并获得列表中的另一个因子。

function GCF(a, b) {
    if (b == 0) return a;
    else return (GCF (b, a % b));
}

function LCM(a, b) {
    return Math.abs(a*b) / GCF(a, b);
}

LCM(11, LCM(12, LCM(13, LCM(14, LCM(15, LCM(16, LCM(17, LCM(18, LCM(19, 20)))))))));

对任意 n 进行处理,不是超级优化,但它很简单:

function LCM_N(n) {
    var x = 1;
    while (n > 1) {
        x = LCM(n, x);
        n--;
    }
    return x;
}

【讨论】:

  • 我想看看对于任意范围长度而不是 20 的长度。
  • 这是最好的方法。
  • LCM_N 没有定义?
【解决方案3】:

所以,您需要 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 的最小公倍数, 20

这与 20,19,18,17,16,15,14,13,12,11 的最小公倍数 (LCM) 相同,因为 1,2,3,4,5,6,7, 8,9,10 都是其他十个数字的因数。

您应该使用 while 循环,因为它们更快。

LCM必须小于或等于20,19,18,17,16,15,14,13,12,11的倍数,所以n可以等于那个开始。

i 可以从序列中所有素数的倍数开始:19*17*13*11*7*5*3*2

break 退出循环。这可能是你花了这么长时间的原因。

我们可以增加 20,因为它是答案之间可能的最小差异。

function lowestCommonMultipleof20Through1(){
  var i = 19*17*13*11*7*5*4*3; 
  var n = 20*19*18*17*16*15*14*13*12*11;
  while(i < n){
    if( i%11 === 0 && 
        i%12 === 0 && 
        i%13 === 0 && 
        i%14 === 0 && 
        i%15 === 0 && 
        i%16 === 0 &&
        i%17 === 0 &&
        i%18 === 0 &&
        i%19 === 0 &&
        i%20 === 0 ){
      console.log(i);
      break;
    }
    i+=20;
  }
}

我几乎立刻就得到了 232792560。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-22
    • 1970-01-01
    • 2021-06-01
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多