【问题标题】:How can we find the i'th greatest element of the array?我们如何找到数组中第 i 个最大的元素?
【发布时间】:2011-03-08 15:28:39
【问题描述】:

使用数据结构自平衡二叉搜索树查找数组中第 n 个最小/最大元素的算法..

阅读帖子:Find kth smallest element in a binary search tree in Optimum way。但是正确答案不清楚,因为我无法弄清楚正确答案,例如我举的一个例子......请多解释一下......

【问题讨论】:

  • 作业不要作弊!
  • 排序并查找第 i 个元素。
  • @amphetamachine : 我认为人们在 6 月的最后一周没有作业!
  • @Yassir:有些学校无论如何都不会在“你放暑假”系统上工作。滑铁卢大学合作社制度采用 4 个月的学校,4 个月的合作社制度。
  • 这不是硬件......我们如何使用自平衡二叉搜索树实现相同......en.wikipedia.org/wiki/…

标签: c algorithm


【解决方案1】:

先对数组进行降序排序,然后取ith 元素。

【讨论】:

  • 这有 O(N log N) 的复杂度,但这项工作可以用 O(N) 的复杂度来完成。
  • 使用选择排序对数组进行排序,但在外循环的第 i 次迭代处停止也有 O(N) 保证复杂度,但实际上会比您的选择算法慢回答。
  • @Jerry:由于几乎所有编程语言都带有高度优化的排序功能,因此节省的代码复杂度通常非常值得额外的 log N 因素。
  • @GregS:你什么意思?那将是 O(N*I),其中 I 是元素的索引。
  • @Daniel:我想这取决于你想要什么。就个人而言,我只会使用已经包含优化的 select 函数的语言/库。
【解决方案2】:

C.A.R. Hoare 的select 算法正是为此目的而设计的。它以 [预期] 线性时间执行,具有对数额外存储空间。

编辑:排序的明显替代方案,然后选择正确的元素具有 O(N log N) 复杂度而不是 O(N)。以排序顺序存储i 最大的元素需要 O(i) 辅助存储,以及大约 O(N * i log i) 复杂度。如果 i 已知先验非常小(例如 1 或 2),则此 可能是一个胜利。对于更一般的用途,select 通常更好。

Edit2:顺便说一句,我没有很好的参考,但在previous answer 中描述了这个想法。

【讨论】:

  • 快速排序基于选择算法。在选择中,您不必处理数组的两侧。在子数组大小变得足够小(大约 2*i)后,您也不必继续处理子数组。
  • 这是一个很好的参考。它被称为快速选择:en.wikipedia.org/wiki/…
  • 另外,您可以在第 436 页的 Skiena 算法设计手册中找到很好的参考。
【解决方案3】:

创建一个排序的数据结构来保存i 元素并将初始计数设置为0。

处理源数组中的每个元素,将其添加到新结构中,直到新结构已满。

然后处理源数组的其余部分。对于每一个大于排序数据结构中最小的,从该结构中删除最小的并放入新的。

处理完源数组中的所有元素后,您的结构将保存i 最大的元素。只需抓住其中的最后一个,您就拥有了 i'th 最伟大的元素。

瞧!

或者,对它进行排序,然后直接抓取i'th 元素。

【讨论】:

    【解决方案4】:

    对于具有非常低的插入和删除最小成本的堆来说,这是一项合适的任务。例如。 pairing heaps。它将具有最坏的 O(n*log(n)) 性能。但由于实施起来并不简单,最好先在其他地方进行检查selection algorithms

    【讨论】:

      【解决方案5】:

      有许多策略可用于您的任务(如果您一开始不关注自平衡树)。

      这通常是速度/内存的权衡。大多数算法需要就地修改数组或O(N) 额外存储。

      自平衡树的解决方案属于后一类,但在这里不是正确的选择。问题是构建树本身需要O(N*log N),它将主导后面的搜索词并给出O(N*log N) 的最终复杂度。因此,您并不比简单地对数组进行排序并使用复杂的数据结构更好......

      一般来说,问题很大程度上取决于与N 相关的i 的大小。如果您想一想,对于i == 1 这很简单,对吧?这叫做找到最大值。

      好吧,同样的策略显然在线性时间内适用于i == 2(携带最多 2 个元素)。它也是微对称的:即如果你需要找到第 N-1 个元素,那么只需携带 2 个最小元素。

      但是,当i 大约为 N/2 或 N/4 时,它会失去效率。携带第 i 个最大元素意味着对大小为 i... 的数组进行排序,因此我们回退到 N*log N 墙上。

      Jerry Coffin 指出了一个简单的解决方案,非常适合这种情况。这是Wikipedia 上的参考。全文还介绍了 Median of Median 方法:它更可靠,但工作量更大,因此通常速度较慢。

      【讨论】:

        【解决方案6】:
        Create an empty list L
        
        For each element x in the original list,
        
            add x in sorted position to L
            if L has more than i elements, 
                pop the smallest one off L
        
        if List2 has i elements, 
            return the i-th element, 
        else 
            return failure
        

        这应该花费 O(N (log (i)))。如果假设 i 为常数,则为 O(N)。

        【讨论】:

        • 你能提供一个例子吗……看起来不错的一个……但不完全理解……
        • i 可以任意大,因此我们必须将其表示为 O(N log i),甚至 O(N log N),而不是 O(N)。后者假设 i 很小,但它可能是 2^82,在这种悲观的情况下,你的算法会做 O(N log N) 的工作,只是为了告诉“没有这样的元素”,对吧?
        【解决方案7】:

        从元素构建一个堆并调用MINi次。

        【讨论】:

          猜你喜欢
          • 2015-06-02
          • 2019-05-31
          • 1970-01-01
          • 2013-01-19
          • 2011-01-24
          • 1970-01-01
          • 2022-12-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多