最大化最小差异

时间:2015-03-02 18:47:34

标签: algorithm

我们以数组A的形式给出N个元素,现在我们必须从N个给定索引中选择K个索引,使得对于任何2个索引i和j,| A [i] -A [j] |的最小值。尽可能大。我们需要告诉这个最大值。

让我们举一个例子:设N = 5,K = 2,数组为[1,5,3,7,11],然后这里的答案是10,因为我们可以简单地选择第一个和最后一个位置并且不同= 11-1 = 10

示例2:设N = 10且K = 3且阵列A为[3 9 6 11 15 20 23],此处答案为8.我们可以选择[3,11,23]或[3,15] ,23]。

现在给出N,K和数组A,我们需要找到这个最大差异。

我们给出1≤N≤10^ 5和1≤S≤10^ 7

2 个答案:

答案 0 :(得分:3)

  1. 让我们对数组进行排序。

  2. 现在我们可以对答案进行二元搜索。

  3. 对于固定的候选x,我们可以贪婪地选择元素(迭代排序的数组并在可能的情况下获取每个元素)。如果我们挑选的元素数量不少于K,则x是可行的。否则,它不是。

  4. 时间复杂度为O(N * log N + N * log (MAX_ELEMENT - MIN_ELEMENT))

    伪代码:

    bool isFeasible(int x):
        cnt = 1
        last = a[0]
        for i <- 1 ... n - 1:
            if a[i] - last >= x:
                last = a[i]
                cnt++
        return cnt >= k
    
    sort(a)
    low = 0
    high = a[n - 1] - a[0] + 1
    while high - low > 1:
        mid = low + (high - low) / 2
        if isFeasible(mid):
           low = mid
        else
           high = mid
    print(low)
    

答案 1 :(得分:0)

我认为这可以作为动态编程问题来处理。首先排序A,然后问题是在A中标记K个元素,使得相邻标记项之间的最小差异尽可能大。作为首发,您始终可以标记第一个和最后一个元素。

从左向右移动,在i = 1..N的每个位置,通过在终止于此位置的子阵列中标记i个元素,计算出可以获得的最大最小差异。通过考虑在您正在处理的位置左侧的每个位置终止的k-1项目的最大最小差异,您可以计算终止于此位置的k项目的最大最小差异。显而易见的事情是将每个可能的位置考虑到你当前正在处理的位置,结束一段具有最小差异的k-1项目,但是你可以在这里进行二分搜索以加快速度。< / p>

一旦您一直工作到右手端,您就知道原始问题的最大可能值。如果你需要知道K元素的放置位置,你可以随时记笔记,这样你就可以回溯找出导致这个解决方案的元素,从右到左工作。