移动窗口的最小/最大可以在O(N)中实现吗?

时间:2012-08-30 05:01:31

标签: arrays algorithm heap max min

我有输入数组A

 A[0], A[1], ... , A[N-1]

我希望函数Max(T,A)返回B代表A在上一个移动窗口大小为T的最大值

 B[i+T] = Max(A[i], A[i+T])

通过使用最大堆来跟踪当前移动窗口A [i]到A [i + T]的最大值,该算法产生O(N log(T))最坏情况。

我想知道有更好的算法吗?也许是O(N)算法

3 个答案:

答案 0 :(得分:25)

使用Deque数据结构可以实现O(N)。它拥有对(价值;指数)。

at every step:

  if (!Deque.Empty) and (Deque.Head.Index <= CurrentIndex - T) then 
     Deque.ExtractHead;
  //Head is too old, it is leaving the window

  while (!Deque.Empty) and (Deque.Tail.Value > CurrentValue) do
     Deque.ExtractTail;
  //remove elements that have no chance to become minimum in the window

  Deque.AddTail(CurrentValue, CurrentIndex); 
  CurrentMin = Deque.Head.Value
  //Head value is minimum in the current window

答案 1 :(得分:6)

它叫做RMQ(范围最小查询)。实际上我曾经写过一篇关于它的文章(使用c ++代码)。见http://attiix.com/2011/08/22/4-ways-to-solve-%C2%B11-rmq/

或者您可能更喜欢维基百科,Range Minimum Query

准备之后,您可以在O(1)

中获取任何给定范围的最大数量

答案 2 :(得分:2)

图像处理中有一个称为数学形态学的子场。您正在实施的操作是此字段中的核心概念,称为 dilation 。显然,这项操作已被广泛研究,我们知道如何非常有效地实施它。

这个问题最有效的算法是1992年和1993年提出的,由van Herk,Gil和Werman独立提出。该算法每个样本只需3次比较,与T的大小无关。

几年后,Gil和Kimmel进一步完善了算法,每个样本只需要进行2.5次比较。虽然方法的复杂性增加可能会抵消较少的比较(我发现更复杂的代码运行得更慢)。我从未实现过这种变体。

HGW算法,因为它被调用,需要两个与输入相同大小的中间缓冲区。对于可笑的大输入(数十亿个样本),您可以将数据分成块并按块进行处理。

在排序中,您可以向前浏览数据,计算大小为T的块的累积最大值。你也是这样做的。每个样本需要对每个样本进行一次比较。最后,结果是这两个临时数组中每个临时数组的最大值超过一个值。对于数据局部性,您可以同时对输入进行两次传递。

我想你甚至可以做一个正在运行的版本,其中临时数组的长度为2*T,但实现起来会更复杂。

  • van Herk,“矩形和八边形内核上局部最小和最大滤波器的快速算法”,模式识别字母13(7):517-521,1992(doi

  • Gil,Werman,“计算2-D min,median和max filters”,IEEE Transactions on Pattern Analysis and Machine Intelligence 15(5):504-507,1993(doi)< / p>

  • Gil,Kimmel,“高效扩张,侵蚀,开启和关闭算法”,IEEE模式分析和机器智能交易24(12):1606-1617,2002(doi

(注意:从this related question on Code Review交叉发布。)