221 lines
9.8 KiB
Markdown
221 lines
9.8 KiB
Markdown
![]() |
---
|
|||
|
title: Smallest Common Multiple
|
|||
|
localeTitle: 最小的共同多重
|
|||
|
---
|
|||
|
如果卡住,请记得使用**`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]`最小公倍数,它们可以被所有数字整除。
|
|||
|
|
|||
|
#### 相关链接
|
|||
|
|
|||
|
* [最小(最小)普通多重](https://en.wikipedia.org/wiki/Least_common_multiple)
|
|||
|
|
|||
|
## 提示: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]);
|
|||
|
```
|
|||
|
|
|||
|
 [运行代码](https://repl.it/CLn2/0)
|
|||
|
|
|||
|
### 代码说明:
|
|||
|
|
|||
|
* 由于最小公分母可能是两个最大数字之一,因此首先检查它们是有意义的,因此对数组进行排序。
|
|||
|
* 创建一个新数组以对所有数字`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数组原型排序](http://forum.freecodecamp.com/t/javascript-array-prototype-sort/14306)
|
|||
|
* [JS for Loops解释](http://forum.freecodecamp.com/t/javascript-for-loop/14666s-Explained)
|
|||
|
* [JS阵列原型推送](http://forum.freecodecamp.com/t/javascript-array-prototype-push/14298)
|
|||
|
* [JS Do While Loop](http://forum.freecodecamp.com/t/javascript-do-while-loop/14662)
|
|||
|
* 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]);
|
|||
|
```
|
|||
|
|
|||
|
 [运行代码](https://repl.it/CLn4/0)
|
|||
|
|
|||
|
### 代码说明:
|
|||
|
|
|||
|
* 第一个基本解决方案需要超过2,000个循环来计算测试用例`smallestCommons([1,13])` ,以及超过400万个循环来计算`smallestCommons([1,25])` 。该解决方案通过使用更有效的算法评估40个循环中的`smallestCommons([1,13])`和40中的`smallestCommons([1,25])` 。
|
|||
|
* 创建一个空数组**范围** 。
|
|||
|
* 使用`for`循环将给定范围之间的所有数字推到**范围** 。
|
|||
|
* 下一个代码块实现了Euclidean算法,该算法用于查找最小的公共倍数。
|
|||
|
|
|||
|
#### 相关链接
|
|||
|
|
|||
|
* [欧几里德算法](https://en.wikipedia.org/wiki/Euclidean_algorithm)
|
|||
|
* [JS Math Max](http://forum.freecodecamp.com/t/javascript-math-max/14682)
|
|||
|
* [JS Math Min](http://forum.freecodecamp.com/t/javascript-math-min/14684)
|
|||
|
|
|||
|
## 高级代码解决方案
|
|||
|
```
|
|||
|
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]);
|
|||
|
```
|
|||
|
|
|||
|
 [运行代码](https://repl.it/MR9P/latest)
|
|||
|
|
|||
|
### 代码说明:
|
|||
|
|
|||
|
* 从提供的**arr中**提取最小值和最大值。
|
|||
|
* 使用前两个数字的最小公倍数初始化**最小**公共。
|
|||
|
* 循环通过当前LCM的范围计算LCM和范围**lcm(a,b,c)= lcm(lcm(a,b),c)的下一个数字** 。
|
|||
|
|
|||
|
#### 相关链接
|
|||
|
|
|||
|
* [JS Function.prototype.apply()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)
|
|||
|
|
|||
|
## 捐款说明:
|
|||
|
|
|||
|
*  **请勿**添加与任何现有解决方案类似的解决方案。如果您认为它**_相似但更好_** ,那么尝试合并(或替换)现有的类似解决方案。
|
|||
|
* 添加解决方案的说明。
|
|||
|
* 将解决方案分为以下类别之一 - **基本** , **中级**和**高级** 。 
|
|||
|
* 如果您添加了任何**相关的主要内容,**请仅添加您的用户名。 (  **_不要_** _删除任何现有的用户名_ )
|
|||
|
|
|||
|
> 看到 [**`Wiki Challenge Solution Template`**](http://forum.freecodecamp.com/t/algorithm-article-template/14272)供参考。
|