给定k个排序数字,将它们变成连续数字的最低成本是多少?

时间:2015-03-23 14:06:40

标签: algorithm sorting contiguous

假设我们有一个 k 数字的排序列表。现在,我们要将此排序列表转换为具有连续数字的列表。允许的唯一操作是我们可以将数字增加/减少一个。执行每个这样的操作将导致总成本增加一。

现在,如何在转换列表时最小化总成本?

我的一个想法是获得排序列表的中位数并排列中位数周围的数字。之后,只需添加新创建的列表中的相应数字与原始列表之间的绝对差异。但是,这只是一种直观的方法。我没有任何证据。

P.S:

Here's an example-
Sorted list: -96, -75, -53, -24.
We can convert this list into a consecutive list by various methods. 
The optimal one is: -58, -59, -60, -61
Cost: 90

这是problem from Topcoder

的子部分

2 个答案:

答案 0 :(得分:4)

假设解决方案的顺序递增,mM是排序列表的最小值和最大值。另一种情况将以同样的方式处理。

每个解决方案由分配给第一个元素的编号定义。如果此数字非常小,则将其增加1将降低成本。我们可以继续增加这个数字,直到成本增加。从这一点来看,成本将不断增长。所以最优将是局部最小值,我们可以通过二进制搜索找到它。我们要搜索的范围是[m - n, M + n],其中n是元素数量:

l = [-96, -75, -53, -24]

# Cost if initial value is x
def cost(l, x):
    return sum(abs(i - v) for i, v in enumerate(l, x))

def find(l):
    a, b = l[0] - len(l), l[-1] + len(l)
    while a < b:
        m = (a + b) / 2
        if cost(l, m + 1) >= cost(l, m) <= cost(l, m - 1): # Local minimum
            return m
        if cost(l, m + 1) < cost(l, m):
            a = m + 1
        else:
            b = m - 1
    return b

测试:

>>> initial = find(l)
>>> range(initial, initial + len(l))
[-60, -59, -58, -57]
>>> cost(l, initial)
90

答案 1 :(得分:1)

这是一个简单的解决方案:

  1. 我们假设这些数字是x, x + 1, x + n - 1。然后费用为sum i = 0 ... n - 1 of abs(a[i] - (x + i))。我们称之为f(x)

  2. f(x)是分段线性的,当x接近+infinity-infinity时,它接近无穷大。这意味着在其中一个终点达到最小值。

  3. 结束点为a[0], a[1] - 1, a[2] - 2, ..., a[n - 1] - (n - 1)。所以我们可以尝试所有这些并选择最好的。