Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 添加新元素并删除最旧元素后列表中的最大元素_Algorithm - Fatal编程技术网

Algorithm 添加新元素并删除最旧元素后列表中的最大元素

Algorithm 添加新元素并删除最旧元素后列表中的最大元素,algorithm,Algorithm,我有一个包含最大元素的整数列表,我需要跟踪列表中的最大元素: [3, 1, 2] (3 is the max) 每一个时间段,我都会得到一个新的随机元素,将其添加到列表的末尾,并在固定时间内删除列表的第一个元素。因此,在当前时间段结束时,我的列表将如下所示: [3, 1, 2] (3 is the max) -> [3, 1, 2, -5] (don't care about max at this moment) -> [1, 2, -5] (no

我有一个包含最大元素的整数列表,我需要跟踪列表中的最大元素:

[3, 1, 2] (3 is the max)
每一个时间段,我都会得到一个新的随机元素,将其添加到列表的末尾,并在固定时间内删除列表的第一个元素。因此,在当前时间段结束时,我的列表将如下所示:

    [3, 1, 2]      (3 is the max)
->  [3, 1, 2, -5]  (don't care about max at this moment)
->  [1, 2, -5]     (now 2 is the max)
public class Element {
  Element PrevInsertionOrder;
  Element NextInsertionOrder;
  Element RankingTreeParent;
  Element RankingTreeLeftChild;
  Element RankingTreeRightChild;
  int Data;
}
我可以在列表中的值上键入一个优先级队列,提供O(log(n))插入和删除,但我想知道是否有更有效的方法(可能是[摊销]恒定时间?)来执行此操作。

案例:

  • New>=CurrentMax和第一个选项:CurrentMax更新为New
  • 新<当前最大值和第一个<当前最大值:不变
  • New=当前最大值:搜索以确定新的CurrentMax 然而:

    为了使第三种情况有效,您需要按插入顺序维护一个(双链接)元素列表,并按大小顺序维护一个树。然后,您只需在列表和树中执行插入/删除操作,并从树中读取新的当前最大值。这与树实现一样高效,O(N)用于构建插入顺序列表,O(N logn)用于构建排名树

    保存列表元素的数据结构如下所示:

        [3, 1, 2]      (3 is the max)
    ->  [3, 1, 2, -5]  (don't care about max at this moment)
    ->  [1, 2, -5]     (now 2 is the max)
    
    public class Element {
      Element PrevInsertionOrder;
      Element NextInsertionOrder;
      Element RankingTreeParent;
      Element RankingTreeLeftChild;
      Element RankingTreeRightChild;
      int Data;
    }
    
    更新:


    通过使用出现次数(而不是上面的第二棵树)维护第二个(双链接)不同键值列表,O(1)执行最大值确定的时间似乎是可能的。

    有O(1)摊销复杂度的算法:

    与德克:

    有两个堆栈:

    如果你能比
    O(log(n))做得更好,我会感到惊讶。
    也许可以试着把这篇文章发布到?即使一个O(1)算法是不可能的,我也会对这样一个算法是不可能的证明感兴趣。可能是一个简化参数,表明如果你有这样一个方法,你可以用O(N)或其他什么来实现排序。你可以用Java中的ArrayList之类的东西来跟踪每个值出现的次数(这是Pieter Geerkens在他的回答中建议的);这有一个丑陋的缺点,那就是会占用O(k)空间,尽管其中k是列表中元素绝对值的最大值。通过使用散列结构来保持计数,可以使其更小,这将花费O(n)个空间和发生计数器的摊销(!)O(1)个时间;当删除最后一次出现的最大值元素时,您仍然需要搜索新的最大值。@torquestomp:正是这种情况。如果您有一个数据结构,可以在少于log(n)(组合时间)的时间内插入和删除项,那么您可以比logn更快地排序。我们已经知道,这样做是不可能的。一些堆变体允许O(1)插入,但删除总是log(n)(有时是摊销的)。这个恒定的时间是如何进行的?如何在O(1)时间内插入到大小排序列表中?这仍然不能满足未来的O(1)要求。树的插入和删除在一般情况下是O(log(n))。@torquestomp:这就是为什么我从文章中删除了该声明,以声明它将受到树实现效率的限制。(最有可能是O(logn),正如你所说。)这个问题明确说明的目的是确定是否存在一个算法可以在连续操作中击败O(logn)运行时,所以这篇文章没有增加任何价值,除非有一个树结构以某种方式保证O(1)插入/删除时间。第二个具有发生次数的链表如何在O(1)中解决此问题?在没有随机访问的情况下,使用链表跟踪出现次数的最佳方法是O(n),因为必须迭代才能找到要插入的元素。为了使第二个链表有用,必须对其进行排序,这不仅有助于跟踪发生次数的复杂性,而且还需要花费额外的O(n)来插入以保持排序。通过重新计算时间表上的后缀最大值,可以得到最坏情况下的O(1)。看到了吗,很好!deque实现特别漂亮。@Davidisenstat您能在回答中解释一下您的数据结构吗(或者在代码中解释一下)?我感兴趣,但C++不是我的母语。@丹在高层次上,每个节点都有一个“max”字段,它存储从那个节点到它后面的某个节点的最大值。我们不断地前后扫描,更新该字段。由于每次push/pop操作只需扫描一步,因此结构是上次扫描更新的节点,然后是当前扫描更新的节点,最后是从未更新的节点。我们维护(i)自上次扫描开始后到达的节点和(ii)自当前扫描开始后到达的节点的最大值。不幸的是,问题出在细节上,我还没来得及写出来。我的库附带了一个详尽的测试套件,用于短序列的操作。