最小公共多无限循环

时间:2016-02-03 14:22:50

标签: javascript algorithm

我正在进行一项名为Smallest Common Multiplier的freeCodeCamp练习。练习的目的如下:

  

找到所提供参数的最小公倍数   被两者平均分配,以及中的所有序号   这些参数之间的范围。

     

范围将是两个数字的数组,不一定是   按数字顺序。

     

e.g。对于1和3 - 找到1和3的最小公倍数   它可以被1到3之间的所有数字整除。

我以为我可以通过将传递给函数的数组中的元素从最小到最大排序来保存它,然后使用for循环检查所有数字是否number % x === 0。然后,我将所有内容封装在一个while循环中,检查分隔符的数量(如果分隔符的数量小于我正在检查的最高数量,则重复该过程。

似乎我写了一个无限循环让我的浏览器崩溃。

function smallestCommons(arr) {

  //sort from smallest to largest
  arr.sort(function(a, b) {
    return a-b;
  });

  var result = 1;
  var divisors = [];

  //while number of divisors !== last number to check
  while(divisors.length < arr[1]) {
    //check if number divides result
    for(var x = arr[0]; x < arr[1]; x++) {
      //if it divides result
      if(result % x === 0) {
        //push it to divisors
        divisors.push(x);
      }
      else {
        //clear divisors
        divisors = [];
      }
    }
    //check next number
    result++;
  }

  return result;
}


smallestCommons([5,1]);

你能指出我做错了什么,并指出如何进行练习吗?

5 个答案:

答案 0 :(得分:1)

因为您询问了如何进行练习:

回想一下,最小公倍数等于:

function lcm(a, b) {
  return Math.abs(a * b) / gcd(a, b);
}

(见:Wikipedia)。 最大公约数函数gcd可以使用Euclidean algorithm实现:

function gcd(a, b) {
  if (!b) {
    return a;
  }
  return gcd(b, a % b);
}

现在已经实现lcm,并且使用数学lcm(a, b, c) === lcm((lcm(a, b), c)这一事实,我们只需要一种方法来生成包含给定start和{{1}的数字范围然后reduce范围到最小公倍数,如下所示:

end

那是一个包装:

function range(start, end) {
  return [...Array(end - start + 1)].map((_, i) => start + i);
}

function smallestCommons(arr) {
  const start = Math.min(...arr);
  const end = Math.max(...arr);

  return range(start, end).reduce(function(a, b) {
    return lcm(a, b);
  });
}

答案 1 :(得分:0)

请注意,您在函数的else部分清除了divisors数组。 这样你就无法通过条件divisors.length >= arr[1]

但是,您的LCM实施根本不起作用

答案 2 :(得分:0)

这是我的javascript解决方案,也许你会发现它有用的参考:

function smallestCommons(arr) {
  var min = Math.min(arr[0], arr[1]);
  var max = Math.max(arr[0], arr[1]);

  var smallestCommon = min * max;

  var doneCalc = 0;

  while (doneCalc === 0) {
    for (var i = min; i <= max; i++) {
      if (smallestCommon % i !== 0) {
        smallestCommon += max;
        doneCalc = 0;
        break;
      }
      else {
        doneCalc = 1;
      }
    }
  }

  return smallestCommon;
}

答案 3 :(得分:0)

您可以将以下功能用于最小的常用乘数。但是,它将在一个非常大的循环中运行,以获得更大的输入和差异。

因此,它取决于您运行代码的环境。如果您在https://jsfiddle.net/qf4snysL/中尝试此代码,您将获得正确的输出。但在FCC中,它可能为输入提供无限循环[18,23]。

function smallestCommons(arr) {
var range = arr.sort();
  //alert(range);
  var array = [];
  for(var i=arr[0];i<=arr[arr.length-1];i++){
  array.push(i);
  }
var x=true;
var LCM=0;
while(x){
  LCM++;
  for(var j = array[0]; j <=array[array.length-1];j++){
    if(LCM % j !==0){
      break;
    }
    else if(j==array[array.length-1]){
    x=false;
    }
  }
}
return LCM;

}
smallestCommons([18,23]);

//noprotect

查看底部的//noprotect,它是出于特殊目的。

答案 4 :(得分:0)

由于许多人似乎正在努力应对这一挑战(我与其他人挣扎......),也许你们发现我的解决方案很有帮助。实际上,这很简单:

// noprotect
function smallestCommons(arr) {

  arr = arr.sort();
  var multiple = 0;


  function test(num) {
    for (var j = arr[0]; j<=arr[1]; j++) {
      if (num % j !== 0) return false;
    }
  return true;
  }


  for (var i = arr[1]*2; i<100000000; i++) {
    if (test(i)){
       multiple = i;
       break;
    }
  }

  return multiple;
}

&#39;测试&#39;函数测试给定数字(&#39; num&#39;)是否是所提供参数的公倍数以及它们之间的所有数字。 for循环遍历所有正数,直到一个数字符合此测试,返回此数字作为我们的解决方案。我们可以跳过一些数字,从最大参数乘以2开始(arr [1] * 2),因为最小公倍数不可能小于此(右?)。但有人可能只是从i = 1开始。希望这有帮助!