【问题标题】:How to find the minimum positive number K for an array to make the array in strictly ascending order如何找到数组的最小正数 K 以使数组严格按升序排列
【发布时间】:2013-09-29 08:45:49
【问题描述】:

如何找到最小正数 K 使得对于数组中的每个项目,从 [-K, K] 中添加或减去一个数字可以导致一个严格升序的数组?

例如:

  • 数组为 [10, 2, 20]
  • 最小 K 为 5,可能的结果是 [10-5, 2+4, 20]
  • k = 4 不行,因为 10-4 == 2+4;数组不能转换为严格的升序

我的猜测如下

定义 f(i, j) = a[i] - a[j] + j-i-1 (要求 i a[j] :所有逆序对)

最小K必须满足条件:

2*K > 最大 f(i,j)

因为如果一对(i,j)不是升序的,a[j]最多只能加K,a[i]最多可以减K,而且a[之间需要留空间给item i] 和 a[j] (因为它是严格的升序), 所以 (a[j] + K) - (a[i] - K) 应该大于 (j-i-1) (它们之间的长度)。

所以 k >= max f(i, j)/2 + 1

问题是我无法证明 k = max f(i, j)/2 + 1 是否可行?


更多线索:

我考虑过找到一种算法来确定给定的 K 是否足够,然后我们 可以使用该算法从可能的最小值开始尝试每个 K 以找到解决方案。

我想出了一个这样的算法:

for i in n->1  # n is array length
if i == n:
    add K to a[i]   # add the max to the last item won't affect order
else:
    # the method is try to make a[i] as big as possible and still < a[i+1]
    find a num k1 in [-K, K] to make a[i] to bottom closest to a[i+1]-1
    if found:
        add k1 to a[i]
    else no k1 in [-K, K] can make a[i] < a[i+1]
        return false
return true

我也是这样的算法对不对

【问题讨论】:

  • 也许这应该放在 cs.SE 或 cstheory.SE 中?
  • 也许吧,但我也想如果我们能找到一个算法来确定一个 K 是否可以,那么我们可以从最小值尝试所有可能的 K,直到我们找到一个解决方案
  • 例如i = 4和j = 5,它们之间的空格为0,即j - i -1

标签: algorithm


【解决方案1】:

我认为你的猜测是正确的,但我也无法证明它:-) 相反,我将从简化你的问题开始

如何找到最小正数K,使得对于数组中的每一项,在[-K, K]中加减一个数都可以得到一个严格递增的数组?

通过“添加”K:

如何找到最小的正数 2*K 使得对于数组中的每一项,从 [0, 2*K] 中添加一个数字可以导致一个严格升序的数组?

我们可以很容易地解决这个问题,方法是迭代数组并跟踪满足条件所需的 2K 值。它与@ruakh 的非常相似,但没有减法:

k2 = 0
last = arr[0]
for each cur in arr from 1
    if cur + k2 <= last
        last ++
        k2 = last - cur
    else
        last = cur
k = ceil ( k2 / 2 )

【讨论】:

  • 使用转换为纯正偏移的想法确实使推理更容易,触感很好。
  • @Bergi 你能解释一下为什么需要更正last++k2 = last - cur 吗?据我了解,如果仍然没有严格增加,您需要进行这些调整。那是对的吗?但我不明白为什么你这些调整会帮助它变得严格增加。
  • @AlanH k2 = last - cur 只需将k2 放入必要的数量,以便[0, k2] 中的xcur + x &gt;= last - 即当前值可以满足要求.是的,last++ 只是为了确保它严格增加而不仅仅是增加。
【解决方案2】:

我觉得你有点想多了。您可以只遍历数组的元素,跟踪 K 的当前最小可能值,以及给定 值的最后一个元素的当前最小可能值>K。每当你发现一个元素证明你的 K 太小,你可以相应地增加它。

例如,在 Java 中:

int[] array = { 10, 2, 20 };
int K = 0, last = array[0];
for (int i = 1; i < array.length; ++i) {
    if (last >= array[i] + K) {
        // If we're here, then our value for K wasn't enough: the minimum
        // possible value of the previous element after transformation is still
        // not less than the maximum possible value of the current element after
        // transformation; so, we need to increase K, allowing us to decrease
        // the former and increase the latter.
        int correction = (last - (array[i] + K)) / 2 + 1;
        K += correction;
        last -= correction;
        ++last;
    } else {
        // If we're here, then our value for K was fine, and we just need to
        // record the minimum possible value of the current value after
        // transformation. (It has to be greater than the minimum possible value
        // of the previous element, and it has to be within the K-bound.)
        if (last < array[i] - K) {
            last = array[i] - K;
        } else {
            ++last;
        }
    }
}

【讨论】:

  • 修正“last”时,会不会比“last”前面的元素小?
  • 哦,对不起,“last”是一个值而不是索引
  • 您好,请您进一步解释一下。我正在解决同样的问题。但不明白你的逻辑。
猜你喜欢
  • 1970-01-01
  • 2016-03-20
  • 2011-06-28
  • 2019-04-14
  • 1970-01-01
  • 2017-03-04
  • 1970-01-01
相关资源
最近更新 更多