从给定数组构造带有一些约束的数组

时间:2012-02-18 17:38:49

标签: algorithm

给定N个元素的数组A[0 .. N - 1],生成一个数组B,使得:

 B[i] = min (A[i], A[i+1], ..., A[i+K-1]). 

(数组B将具有完全(N-k + 1)个元素。

时间复杂度应优于O(N * k)

我正在考虑使用minheap ......但是heapify会增加复杂性 蛮力也是O(n * k)

空间复杂度s'd也小于等于O(k)

这是一个例子

Input: 
A={ 2,1,3,2,5,7,1}, N=7,k=3

Output:
B={1,1,2,2,1}

4 个答案:

答案 0 :(得分:4)

要解决此问题,您可以使用queue in which push_rear(), pop_front() and get_min() are all constant time operations

将数组k中的第一个A元素推送到此队列。然后继续从数组A填充队列,同时从中弹出元素并将最小值附加到数组B

时间复杂度为O(N)。空间复杂度为O(k)

答案 1 :(得分:0)

在O(N)而不是O(N * k)中执行此操作的关键是不计算给定的公式 每个条目B[i] = min (A[i], A[i+1], ..., A[i+K-1]),但会逐步更新。

在每个步骤中都有K个排序条目的结果集。

第一步:从前K个条目计算B [0]并将结果分配给B[0]

第一步增量: 计算B[1]您只需将A[i+K]添加到结果集中,并从结果集中减去A[0],而不是再次添加K个条目。

每增加一步: 因此,对于每个附加索引,您只有两个结果集更新。

总的来说,你有线性的复杂性。

答案 2 :(得分:0)

第1步

编写具有“减少键”功能的(最小 - )优先级队列。这意味着您可以转到节点(例如通过指针),减少其值并更新堆(优先级队列)。

操作decrease_key将是O(log(k))k是优先级队列中元素的数量。

第2步

考虑以下操作:

  • Add A[i]:这包括将A[i]添加到优先级队列,以及在优先级队列中创建的节点中保留指针,例如C[i]。这是O(log(k))

  • Remove A[i]:这意味着转到包含A[i](通过C[i])的节点,将其值减小到负无穷大,然后将其从堆顶部删除。这也是O(log(k))

第3步

初始化优先级队列:将k的第一个A元素添加到优先级队列中。这是O(k*log(k))

第4步

像这样填充B的元素:

for i = 1 to n-k+1
    B[i] = pQ.top
    Remove A[i]
    Add A[i+k]

这部分是O(n*log(k))

最终分析

此算法的总时间顺序为O(n*log(k))。空间顺序为O(k)。这是优先级队列的k个节点和指向那些节点的k指针(数组C),如果天真地实现,它们将成为O(n)

答案 3 :(得分:0)

从我之前的回答:Finding maximum for every window of size k in an array,其中列出了四种不同的O(n)解决方案。

0)通过结合两个经典的面试问题,可以实现O(n)时间解决方案:

  • 创建一个堆栈数据结构(称为MaxStack),在O(1)时间内支持push,pop和max。

    这可以使用两个堆栈完成,第二个堆栈包含到目前为止看到的最小值。

  • 使用堆栈建模队列。

    这可以使用两个堆栈来完成。入队进入一个堆叠,出列的是另一个。

对于这个问题,我们基本上需要一个队列,它在O(1)(摊销)时间内支持入队,出队和最大。

我们通过使用两个MaxStack建模队列来结合上述两个。

为了解决这个问题,我们对k个元素进行排队,查询max,dequeue,将第k + 1个元素排队,查询max等。这将为每个k大小的子数组提供最大值。

我相信还有其他解决方案。

1)

我相信队列的想法可以简化。我们为每个k维护一个队列和一个最大值。我们将一个新元素排入队列,并将所有不大于新元素的元素取消。

2)保持两个新阵列,每个k块保持运行最大值,一个阵列为一个方向(从左到右/从右到左)。

3)使用锤子:在O(n)时间内预处理以进行范围最大查询。

上述1)解决方案可能是最优化的。