(Предположим, что числа положительные.)
Наименьший LCM, вероятно, будет получен из наименьших элементов, поэтому для сокращения пробных значений можно отсортировать массив.
int[] v = { ... };
int minLCM = Integer.MAX_VALUE;
int bestVi = -1;
int bestVj = -1;
Arrays.sort(v);
for (int i = 0; i < v.length; ++i) {
int vi = v[i];
// _____________
for (int j = i + 1; j < v.length && v[j] < minLCM; ++j) {
int vj = v[j];
int lcm = lcm(vi, vj);
if (lcm < minLcm) {
minLCM = lcm;
bestVi = vi;
bestVj = vj;
}
}
}
Для обрезки:
lcm(vi, vj) >= vi
lcm(vi, vj) >= vj
(lcm(vi, vj) <= vi*vj
Это сокращение может быть выполнено в цикле for-j только как vj >= vi
.
Лучшее сокращение можно было бы сделать, если бы вместо числа у вас был список (не более ²log value
) простых множителей. Поскольку факторизация тоже стоит, можно просто попробовать, например, (2, 3, 5, 7).
Улучшение цикла также может быть достигнуто заменой обоих вложенных циклов так, чтобы наименьший (vi, vj) был первым. Выше (v0, v100) предшествует (v1, v2). Цикл по возрастанию i+j.
i j
0 1
0 2
0 3
1 2
0 4
1 3
0 5
1 4
2 3
...
(Математика для счетчиков циклов с использованием диагоналей — хорошая головоломка. Это действительно нужно сделать.)
Хотя все еще O(n²)
это может сработать.
Иногда также имеет значение язык программирования, и в этих контекстах часто можно увидеть вклад C. В таком случае использование Ruby может оказаться контрпродуктивным.
person
Joop Eggen
schedule
17.04.2019