比使用JavaScript

时间:2016-03-29 22:17:10

标签: javascript algorithm

我编写了一个算法,它返回两个整数的最小公倍数,可以被两者平均分割,也可以在初始两个整数之间的范围内均匀地除以所有序列整数。

我的算法适用于最小公倍数是一个相当低的数字的数字。对于最小公倍数是一个非常大的数字(例如[1,13]其360360),我的算法会中断,因为它依赖于越来越多的循环运行。

我在下面发布了我的代码。它似乎很长,但问题部分接近开头,其余代码是为上下文添加的。

是否有更有效的解决方案,运行越来越多的循环迭代以返回更大的数字?

// If mystery failure occurs, examine i & j loop limits.
function smallestCommons(arr) {
var firstArray = [];
var secondArray = [];
var commonNums = [];
var sequential = [];

// Sort the array from lowest to highest
arr.sort(function(a,b) {
  return a-b;
});

// Assing arr values to vars so that original data stays intact
var array0 = arr[0];
var array1 = arr[1];
//console.log(arr);
// Find all multiples of both inputs.

// THIS IS THE PROBLEM SECTION
for (var i = 0; i < 1000000; i++) {
firstArray.push(arr[0] * (i+1));
}
for (var j = 0; j < 1000000; j++) {
secondArray.push(arr[1] * (j+1));
}
// THAT WAS THE PROBLEM SECTION

// Find common multiples.
for (var k = 0; k < firstArray.length; k++) {
  for (var l = 0; l < secondArray.length; l++) {
if (firstArray[k] == secondArray[l]) {
  commonNums.push(firstArray[k]);
} // End if.
} // End l loop.
} // End k loop.

// Find sequential numbers in range between input parameters.
for (var m = 0; m < array1; m++) {
if (array0 + 1 !== array1) {
  sequential.push(array0 += 1);
} // End of if.
} // End of m loop.

// Find commonNums divisible by arr && sequential to produce a whole number.
// commonNums [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75]
// arr [1,5]
// sequential [ 2, 3, 4 ]
for (var n = 0; n < commonNums.length; n++) {
    var match = true;
    for (var o = 0; o < sequential.length; o++) {
        for (var p = 0; p < arr.length; p++) {
            if (commonNums[n] % arr[p] !== 0 || commonNums[n] % sequential[o] !== 0) {
                match = false;
            }
        }
    }
    if(match) {
console.log(commonNums[n]);
    }

} // End of n loop.

} // End function.

smallestCommons([1,13]);

2 个答案:

答案 0 :(得分:1)

你做的事情没有多大意义,而且很难阅读。解决这个问题你需要知道的只是一点数学。这个数学告诉你:

lcm(a, b) = a * b / gcd(a, b)
lcm(a,b,c) = lcm(a,lcm(b,c))

翻译成这样的东西:

function gcd(a, b){
  while (b !== 0) {
    var tmp = a;
    a = b;
    b = tmp % b;
  }
  return a
}

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

function lcm_arr(arr){
  var res = 1;
  for (var i = 0; i < arr.length; i++){
     res = lcm(res, arr[i]);
  }
  return res;
}

在不到一秒的时间内为您提供结果: lcm_arr([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])

答案 1 :(得分:0)

听起来像是一个使用recursion的好地方,因为当数字差异为1时(例如trends/placetrends/place取决于方向),您有一个坚实的基本情况,其余(序列)将递增较小或递减递归调用中较大的数字。这可以节省你很多CPU周期。