9.4 KiB
9.4 KiB
title | localeTitle |
---|---|
Smallest Common Multiple | 最小的共同多重 |
如果卡住,请记得使用**Read-Search-Ask
** 。尝试配对程序并编写自己的代码
问题说明:
两个数字之间的最小公倍数是两个数字可以分成的最小数字。这个概念也可以扩展到两个以上的数字。
我们首先可以从找到两个数字之间的最小公倍数开始。天真地,你可以开始写出每个数字的多个,直到你写出两个数字都存在的倍数。
一个例子是数字3
和4
。 3
的倍数是3, 6, 9, 12, 15, 18, ...
, 4
的倍数是4
4, 8, 12, 16, 20, ...
我们在两个列表中遇到的第一个最小数字是12
所以这是3
到4
之间的最小公倍数。
这个问题可能会令人困惑,因为大多数人只会查找两个数字的最小公倍数,但会忘记关键字范围 。但是,这意味着如果给出[1,5]
,那么你必须检查所有数字[1,2,3,4,5]
最小公倍数,它们可以被所有数字整除。
相关链接
提示:1
创建一个数组,其中包含原始数组中缺少的所有数字,以便更容易检查何时必须检查偶数除法。
现在尝试解决问题
提示:2
您可以使用余数运算符( %
)来检查除法的提示是否为0,这意味着它可以被整除。
现在尝试解决问题
提示:3
如果您将数组从最大到最小排序,那么您可以使用前两个数字作为最小公共倍数的第一个检查。这是因为它们更可能是最小的普通倍数而不是较低的数字。
现在尝试解决问题
扰流警报!
提前解决!
基本代码解决方案
function smallestCommons(arr) {
// Sort array from greater to lowest
// This line of code was from Adam Doyle (http://github.com/Adoyle2014)
arr.sort(function(a, b) {
return b - a;
});
// Create new array and add all values from greater to smaller from the
// original array.
var newArr = [];
for (var i = arr[0]; i >= arr[1]; i--) {
newArr.push(i);
}
// Variables needed declared outside the loops.
var quot = 0;
var loop = 1;
var n;
// Run code while n is not the same as the array length.
do {
quot = newArr[0] * loop * newArr[1];
for (n = 2; n < newArr.length; n++) {
if (quot % newArr[n] !== 0) {
break;
}
}
loop++;
} while (n !== newArr.length);
return quot;
}
// test here
smallestCommons([1,5]);
代码说明:
- 由于最小公分母可能是两个最大数字之一,因此首先检查它们是有意义的,因此对数组进行排序。
- 创建一个新数组以对所有数字
newArr
进行排序。 - 使用降序
for
循环(var i = arr[0]; i >= arr[1]; i--
)在新数组中添加从最大到最小的数字。 - 声明商的变量,以便我们可以在循环外访问它们:
- 那将是我们最小的共同倍数(
quot
)的商 - 我们正在检查的循环数(
loop
) - 数组的索引(
n
)
- 那将是我们最小的共同倍数(
- 使用
do
while
循环来检查我们需要什么,而n
与新数组的长度不同。 - 在
do
部分中,我们将乘以第一个数字,乘以循环次数乘以第二个数字(quot = newArr[0] * loop * newArr[1];
)。 loop
部分将允许我们增加我们检查的数量超出我们所拥有的最大数量,而无需更改算法。- 我们输入一个
for
循环,它将从n
n < newArr.length
1(loop++
),同时它小于具有所有数字的数组(n < newArr.length
)。 - 如果商不均匀分配(
quot % newArr[n] !== 0
),则停止循环(break;
)。如果它是偶数,那么检查数组中的下一个元素(n++
),直到它不均匀或我们找到答案。 - 在循环之外,增加循环的值(
loop++
)。 - 在循环结束时返回商(
return quot;
)。
注意:如果数组只有两个元素,则for
循环永远不会被使用,返回值是所述数字的乘积。
相关链接
- JS数组原型排序
- JS for Loops解释
- JS阵列原型推送
- JS Do While Loop
- string.length减
中级代码解决方案:
function smallestCommons(arr) {
var range = [];
for (var i = Math.max(arr[0], arr[1]); i >= Math.min(arr[0], arr[1]); i--) {
range.push(i);
}
// can use reduce() in place of this block
var lcm = range[0];
for (i = 1; i < range.length; i++) {
var GCD = gcd(lcm, range[i]);
lcm = (lcm * range[i]) / GCD;
}
return lcm;
function gcd(x, y) { // Implements the Euclidean Algorithm
if (y === 0)
return x;
else
return gcd(y, x%y);
}
}
// test here
smallestCommons([1,5]);
代码说明:
- 第一个基本解决方案需要超过2,000个循环来计算测试用例
smallestCommons([1,13])
,以及超过400万个循环来计算smallestCommons([1,25])
。该解决方案通过使用更有效的算法评估40个循环中的smallestCommons([1,13])
和40中的smallestCommons([1,25])
。 - 创建一个空数组范围 。
- 使用
for
循环将给定范围之间的所有数字推到范围 。 - 下一个代码块实现了Euclidean算法,该算法用于查找最小的公共倍数。
相关链接
高级代码解决方案
function smallestCommons(arr) {
// range
let min = Math.min.apply(null, arr);
let max = Math.max.apply(null, arr);
let smallestCommon = lcm(min, min + 1);
while(min < max) {
min++;
smallestCommon = lcm(smallestCommon, min);
}
return smallestCommon;
}
/**
* Calculates Greatest Common Divisor
* of two nubers using Euclidean algorithm
* https://en.wikipedia.org/wiki/Euclidean_algorithm
*/
function gcd(a, b) {
while (b > 0) {
let tmp = a;
a = b;
b = tmp % b;
}
return a;
}
/**
* Calculates Least Common Multiple
* for two numbers utilising GCD
*/
function lcm(a, b) {
return (a * b / gcd(a, b));
}
// test here
smallestCommons([1,5]);
代码说明:
- 从提供的arr中提取最小值和最大值。
- 使用前两个数字的最小公倍数初始化最小公共。
- 循环通过当前LCM的范围计算LCM和范围lcm(a,b,c)= lcm(lcm(a,b),c)的下一个数字 。
相关链接
捐款说明:
- 请勿添加与任何现有解决方案类似的解决方案。如果您认为它**相似但更好** ,那么尝试合并(或替换)现有的类似解决方案。
- 添加解决方案的说明。
- 将解决方案分为以下类别之一 - 基本 , 中级和高级 。
- 如果您添加了任何**相关的主要内容,**请仅添加您的用户名。 ( 不要 删除任何现有的用户名 )