algorithm – 查找将数组转换为算术级数的最低成本

我最近在一次采访中遇到了这个问题.我无法想出一个算法.

给定一个未排序的整数数组,我们必须找到将此数组转换为算术级数的最低成本,如果在数组中更改了任何元素,则会产生1个单位的成本.此外,元素的值介于(-inf,inf)之间.

我有点意识到DP可以在这里使用,但我无法解决这个问题.价值观有一些限制,但我不记得了.我只是在寻找高级伪代码.

最佳答案
Louis Ricci有正确的基本思想,即寻找最大的现有算术级数,但假设它必须出现在一次运行中,而实际上这个级数的元素可以出现在任何位置的子集中,例如:

1 42 3 69 5 1111 2222 8

只需要4个更改:

  42   69   1111 2222
1    3    5           8

要计算这一点,请注意每个AP都有一个最右边的元素.我们可以假设输入向量的每个元素i依次是最右边的AP位置,并且对于每个这样的i考虑i的左边的所有位置j,确定每个(i,j)组合隐含的步长,并且当这是整数(表示有效的AP),向暗示此步长的元素数加1,并在位置i结束 – 因为所有这些元素都属于同一个AP.总体最大值是最长的AP:

struct solution {
    int len;
    int pos;
    int step;
};

solution longestArithProg(vector<int> const& v) {
    solution best = { -1, 0, 0 };

    for (int i = 1; i < v.size(); ++i) {
        unordered_map<int, int> bestForStep;
        for (int j = 0; j < i; ++j) {
            int step = (v[i] - v[j]) / (i - j);
            if (step * (i - j) == v[i] - v[j]) {
                // This j gives an integer step size: record that j lies on this AP
                int len = ++bestForStep[step];
                if (len > best.len) {
                    best.len = len;
                    best.pos = i;
                    best.step = step;
                }
            }
        }
    }

    ++best.len;     // We never counted the final element in the AP
    return best;
}

上面的C代码使用O(n ^ 2)时间和O(n)空间,因为它遍历每对位置i和j,对每个位置执行单个散列读取和写入.要回答原始问题:

int howManyChangesNeeded(vector<int> const& v) {
    return v.size() - longestArithProg(v).len;
}

转载注明原文:algorithm – 查找将数组转换为算术级数的最低成本 - 代码日志