最大化最小元素

时间:2017-11-13 12:38:58

标签: arrays algorithm

我们有一组N个正元素。我们可以在这个数组上执行M操作。在每个操作中,我们必须选择长度为W的子阵列(连续)并将每个元素增加1.阵列的每个元素最多可以增加K倍。 我们必须执行这些操作,以使数组中的最小元素最大化。

1 <= N,W <= 10 ^ 5

1 <= M,K <= 10 ^ 5

时间限制:1秒

我可以想到一个O(n ^ 2)解决方案,但它超出了时间限制。有人可以为此提供O(nlogn)或更好的解决方案吗?

P.S.-这是一个面试问题

2 个答案:

答案 0 :(得分:0)

如果我们将数组的副本按升序排序,将每个元素指向其原始索引,该怎么办?在增加元素时考虑优先级顺序。此外,最终的运营顺序是否重要?

一旦最低元素到达下一个最低元素,那么必须增加什么?如果我们对任何一个元素应用k操作,那么应用w这些增量是否重要?

答案 1 :(得分:0)

它在Google采访中被问到,我通过在范围逻辑中使用滑动窗口,堆和增量来解决。我将分三部分解决问题:

  1. 找出大小为W的每个子数组中的最小值。这可以通过使用带有优先级队列的滑动窗口在 O(n)中完成。每个窗口的最大值必须插入具有3个变量的 min-heap :[array_value,left_index,right_index]

  2. 现在,将辅助数组初始化为大小为N的0。对堆执行 M 次弹出操作,并在每次弹出操作中执行3个任务:

    值,left_index,right_index = heap.pop()#最小弹出的理论函数

    将值增加1, 在left_index的辅助数组中增加1,在in中减少1 right_index + 1处的辅助数组

    再次将此对插入堆中。 [具有递增的值和相同的索引]

  3. 执行M次操作后,将遍历给定数组与辅助数组,并将累加总和添加到数组中索引“ i”处元素的索引“ i”。

返回数组的最小值。

时间复杂度

O(N) <-表示每个窗口+建筑堆中的最小元素。

O(M * logN) <-提取并插入堆中。

O(N) <-用于遍历以增加累加和。

因此,总体上是 O(N + M * logN + N),这是 O(M * logN)

空间复杂度

O(N) <-额外的数组+堆。

上面没有什么可以很容易地优化的东西,例如在堆中插入值,只能插入left_index,并且right_index = left_index + k。

我的代码

from heapq import heappop, heappush
from collections import deque


def find_maximised_minimum(arr, n, m, k):

    """
    arr -> Array, n-> Size of array
    m -> increment operation that can be performed
    k -> window size
    """

    heap = []
    q = deque()
    # sliding window + heap building
    for i in range(k):
        while q and arr[q[-1]] > arr[i]:
            q.pop()
        q.append(i)

    for i in range(k, n):
        heappush(heap, [arr[q[0]], i - k, i - 1])
        while q and q[0] <= i - k:
            q.popleft()
        while q and arr[q[-1]] > arr[i]:
            q.pop()
        q.append(i)
    
    heappush(heap, [arr[q[0]], n - k, n - 1])

    # auxiliary array
    temp = [0 for i in range(n)]

    # performing M increment operations
    while m:
        top = heappop(heap)
        temp[top[1]] += 1
        try:
            temp[top[2] + 1] -= 1
        except:
            # when the index is last, so just ignore
            pass
        top[0] += 1
        heappush(heap, top)
        m -= 1

    # finding cumulative sum 
    sumi = 0
    for i in range(n):
        sumi += temp[i]
        arr[i] += sumi
    print(min(arr))


if __name__ == '__main__':
    # find([1, 2, 3, 4, 5, 6], 6, 5, 2)
    # find([73, 77, 60, 100, 94, 24, 31], 7, 9, 1)
    # find([24, 41, 100, 70, 97, 89, 38, 68, 41, 93], 10, 6, 5)
    # find([88, 36, 72, 72, 37, 76, 83, 18, 76, 54], 10, 4, 3)
    find_maximised_minimum([98, 97, 23, 13, 27, 100, 75, 42], 8, 5, 1)