如何跟踪fifo查询的最大/最小值

时间:2012-07-19 18:34:51

标签: algorithm

我有一个fifo查询,我放置并弹出双打。 每次更新后我都需要max和min值。我不需要查询中这些值的位置(或索引)。 如何有效地做到这一点? log(N)或甚至可能是O(1)?

upd:找到了这个Implement a queue in which push_rear(), pop_front() and get_min() are all constant time operations

2 个答案:

答案 0 :(得分:3)

这是一个棘手的问题。请考虑以下事项:

在任何给定时间说你的fifo的大小是N. 假设您只使用一对浮动来跟踪最小值和最大值。 假设fifo的大小保持相当稳定。

因此,我们可以假设队列中的一个“操作”在逻辑上由一个推送和一个弹出组成。

假设您正在比较处理此问题的两种方法:一种使用堆对,另一种使用天真的比较和搜索。

对于堆方法:

每个操作,你推到列表和两个堆,然后从列表和两个堆弹出。堆操作总是O(log(n))并且列表操作是O(1),因此当N很大时,一个操作的时间复杂度是O(log(N))平均情况。重要的是要注意,无论当前弹出的元素是min还是max元素,堆操作总是如此复杂。因此,N个操作的时间复杂度为O(N * log(N))。

对于天真的方法:

每个操作,您按下并弹出列表,并将弹出的项目与存储的最小值和最大值进行比较。如果该项与任何一项相同,则在列表中搜索具有相等值的项(在这种情况下,您提前中断)或以其他方式搜索列表的其余部分,直到找到下一个最佳元素。然后,您可以使用下一个最佳值更新最小值/最大值。该方法具有O(1)典型情况和O(N)最坏情况(最小或最大需要更新)。重要的是要注意,对于某些N个数字的范围,您需要更新min和max的次数变为常数,并且您不会变为N的次数。因此,N个操作的时间复杂度为上)。天真的情况实际上比更先进的解决方案更好。

那就是说,我认为堆不能有效地删除元素,所以你会遇到很多麻烦。

因此,请考虑以下伪代码:

queue fifo;
float min, max;

void push(float f)
{
    if (fifo.size == 0)
    {
        min = f;
        max = f;
    }
    else if (f > max) max = f;
    else if (f < min) min = f;

    fifo.push(f);
}

float pop()
{
    if (fifo.size == 0) return (*((float *)NULL)); // explode
    float f = fifo.pop();
    if (fifo.size == 0)
    {
        min = NaN;
        max = NaN;
        return f;
    }
    if (f == max) search_max(fifo);
    if (f == min) search_min(fifo);
    return f;
}

search_max(queue q)
{
    float f = min;
    for (element in q)
    {
        if (element == max) return;
        if (element > f) f = element;
    }
    max = f;
}

search_min(queue q)
{
    float f = max;
    for (element in q)
    {
        if (element == min) return;
        if (element < f) f = element;
    }
    min = f;
}

答案 1 :(得分:0)

如何使用堆(http://en.wikipedia.org/wiki/Heap_%28data_structure%29)。你可以有两堆。一个用于提取min和一个用于max(因为单个堆不能同时提取min和max)。它也不需要任何空间开销,Big O是log n。