本文已参与「新人创作礼」活动,一起开启掘金创作之路。
问题描述
给一个数组,如何求数组中所有元素的最小公倍数?
思路
首先可以用一个暴力解法,两两求出数组元素的最小公倍数,然后对于求得的最小公倍数数组重复这个操作直至最后的最小公倍数数组中只有一个值,那么该值即为所有数的最小公倍数
这么做可能会造成最终的数值过大,这里给出一种更实用的方法
已知,每个数都可以分解成一定数目的质因数的乘积,于是可以求出数组所有元素的质因数,这些质因数的乘积就是整个数组的最小公倍数
具体解法概述如下:
- 初始时设置 lcm 为 1,并设置标记 count 为统计当前数组中 1 的个数(如果数组元素都为 1,即表示当前 lcm 值为整个数组的最小公倍数),以及一个初始的因数 div 为 2
- 在 count 小于 数组长度时重复循环,每次循环时设置一个标志位 isDivided,用于表示当前因数是否需要更新,然后遍历数组,若数组有不为 1 的元素且能整除当前的因数 div,则设置 isDivided 为 true,表示数组中还有元素的因数为当前因数。遍历结束后,根据标志位选择更新 lcm 还是因数 div
具体看代码:
public int fingLCM(int[] nums) {
// 标志位,用于表示因数是否需要更新
boolean isDivided;
int n = nums.length;
// 表示当前数组中 1 的个数
int count = 0;
// 当前计算的最小公倍数
int lcm = 1;
// 当前的因数
int div = 2;
// 在数组中还有非 1 元素时重复循环
while (count != n) {
// 初始化标记为
isDivided = false;
// 初始化计数
count = 0;
// 遍历数组
for (int i = 0; i < n; i++) {
// 若当前数不为 1 且可以整除因数 div
if (nums[i] != 1 && nums[i] % div == 0) {
// 更新标志位
isDivided = true;
// 更新当前数
nums[i] /= div;
}
// 更新数组中 1 的个数
if (nums[i] == 1) {
count++;
}
}
// 若标记位为 true,则当前因数在本轮使用过
if (isDivided) {
// 更新最小公倍数
lcm *= div;
} else { // 否则更新因数,表示数组元素中不在包含本因数
div++;
}
}
return lcm;
}