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

ipo*_*ppo 14 arrays algorithm heap max min

我有输入数组A.

 A[0], A[1], ... , A[N-1]
Run Code Online (Sandbox Code Playgroud)

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

 B[i+T] = Max(A[i], A[i+T])
Run Code Online (Sandbox Code Playgroud)

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

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

MBo*_*MBo 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
Run Code Online (Sandbox Code Playgroud)


ilo*_*ahz 6

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

或者您可能更喜欢维基百科,范围最小查询

准备之后,您可以获得任何给定范围的最大数量 O(1)


Cri*_*ngo 5

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

van Herk、Gil 和 Werman 于 1992 年和 1993 年独立提出了解决该问题的最有效算法。该算法需要对每个样本进行 3 次比较,与 的大小无关T

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

HGW 算法,正如其名称,需要两个与输入大小相同的中间缓冲区。对于非常大的输入(数十亿个样本),您可以将数据分割成块并逐块处理。

按排序,您向前遍历数据,计算 size 块上的累积最大值T。你向后走也做同样的事情。其中每一项都需要对每个样本进行一次比较。最后,结果是这两个临时数组中每个值的最大值。对于数据局部性,您可以同时对输入进行两次传递。

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

  • van Herk,“矩形和八角形内核上局部最小和最大滤波器的快速算法”,Pattern Recognition Letters 13(7):517-521, 1992 ( doi )

  • Gil, Werman,“计算 2-D 最小值、中值和最大值滤波器”,IEEE Transactions on Pattern Analysis and Machine Intelligence 15(5):504-507,1993 ( doi )

  • Gil, Kimmel,“高效的膨胀、腐蚀、开闭算法”,IEEE Transactions on Pattern Analysis and Machine Intelligence 24(12):1606-1617, 2002 ( doi )

(注意:从Code Review 上的相关问题交叉发布。)