查找给定数组中LCM值最小的对

时间:2019-04-17 09:51:23

标签: arrays algorithm data-structures dynamic-programming

我最近遇到了一个竞争性编程竞赛的问题。给定一个整数数组,找到LCM值最小的一对数组元素的索引。

我知道有一个简单的双循环O(n ^ 2)解决方案,但是正如预期的那样,它给出了时间限制例外。我听说动态编程用于优化蛮力方法,但是我不知道如何将这个问题分为子问题,从而没有一个最佳子结构。

我能否获得使用DP解决此问题的任何指导?还是更好的方法?谢谢。

1 个答案:

答案 0 :(得分:0)

(假设为正数。)

最小的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

只能在{-{1}}中进行for-j循环的修剪。

如果一个数字包含一个(最多vj >= vi)个主要因素的列表,则可以进行更好的修剪。 由于分解成本也很昂贵,因此例如可以尝试(2,3,5,7)。

也可以通过替换两个嵌套循环来实现更好的循环,从而使最小的(vi,vj)首先出现。高于(v0,v100)在(v1,v2)之前。遍历不断增加的i + j。

²log value

(使用对角线的循环计数器的数学运算是一个很好的难题。应该做到。

尽管i j 0 1 0 2 0 3 1 2 0 4 1 3 0 5 1 4 2 3 ... 仍然可行。

有时编程语言也很重要,人们常常在这种情况下看到C的贡献。在这种情况下,使用Ruby可能会适得其反。