【问题标题】:Sorting using a custom API - removeAndAppend使用自定义 API 进行排序 - removeAndAppend
【发布时间】:2013-08-20 14:12:23
【问题描述】:

我们得到了一个 API -

removeAndAppend(val)
//Removes val and appends it to the given collection 

我们需要使用这个 API 对集合进行排序..

我知道我可以通过 -

for i <- N to 1
    extract max //in O(n) 
    removeAndAppend.. //Consider this O(1)

这是二次的..

问题是我能做得比这更好吗..?

编辑:我们可以对集合执行 READ 操作,例如 - compare(val1, val2)

【问题讨论】:

  • 这是什么 API?什么语言?还是这个伪代码?
  • 我可以想象一个链表可以让你在恒定时间内删除AndAppen..我不认为语言/伪代码在这里很重要..如果我错了请纠正我
  • 看看this question 关于Java 中的插入和删除。听起来像您要找的东西吗?

标签: performance algorithm


【解决方案1】:

没有额外的数据结构/常量空间限制:

你描述的O(n<sup>2</sup>)算法本质上是selection sort

如果您可以访问某种迭代器(如果没有,您将如何访问集合中的元素?),我相信使用自定义 merge-sort 可以做得更好,如下所示:

  • 比较元素 1 和 2。removeAndAppend 较小的元素,然后removeAndAppend 剩余的元素。对元素 3 和 4、5 和 6、...以及元素 n-1 和 n 执行相同操作。

    现在您将对每个包含 2 个元素的子集合进行排序。

  • 合并索引 (1,2) 和 (3,4)。为此,从头开始有 2 个迭代器。首先将一个增加两次。然后像往常一样使用removeAndAppend 函数进行合并排序。对 (5,6) 和 (7,8)、(9,10) 和 (11,12)、... 和 (n-3,n-2) 和 (n-1,n) 执行相同操作。

    现在您将对每个包含 4 个元素的子集合进行排序。

  • 合并大小与上述类似的 4 个集合,然后合并 8、16、32 等,直到达到集合大小。

整个过程如下所示:

// setSize is how large sets we're currently merging
for setSize = 1; setSize <= n/2; setSize *= 2
  iterator left = begin
           right = begin
  for pos = 1 to n/(2*setSize)
    // here right and left are both at the beginning
    // even after the previous iteration of the loop,
    //   since we've removed and appended all other elements
    // so we only need to increase right by setSize
    right += setSize

    for i = 1 to 2*setSize
      if (left.value <= right.value)
        removeAndAppend(left)
      else
        removeAndAppend(right)

以上只是一个基本的草稿,它可能不是 100% 正确的,并且没有考虑到集合不是 2 的幂的情况(这种情况经常发生)。在这种情况下你需要小心,否则你可能会绕回,或者走得不够远,最终得到一个部分排序的集合。

复杂性分析应该与常规合并排序几乎相同,并产生O(n log n) 运行时间。

有额外的数据结构/没有常数空间限制:

将所有元素提取到另一个集合中,在O(n log n) 中对其进行排序(使用您选择的排序算法)并遍历已排序的集合,对每个元素的原始集合调用removeAndAppend

如果您不允许提取元素,则仍然可以通过使用索引集合来使用此方法,并且要进行比较,只需查找适用的元素即可。但是,为了提高效率,您需要按索引进行恒定时间查找。

【讨论】:

  • 我一直在寻找这个 - “如果有一个恒定的空间限制(这似乎是最可能的情况),我认为你不能做得比二次方更好。”我认为引用的陈述是正确的,因为在使用 removeAndAppend 之前我需要做一些处理(一些排序逻辑)。在 N 个元素上 removeAndAppend 绝对是线性时间。我们能证明二次是我们能得到的最好的......?我不擅长这个:(
  • 如果没有 O(n) 空间,我无法进行合并排序。我期待有一些东西在适当的位置。或者在最恒定的空间中。但我明白你描述的想法。tnx
  • 我们重用了与输入相同的空间,因此它应该归类为 O(1) extra 空间(这通常是我们定义空间复杂度的方式)。跨度>
【解决方案2】:

您可以使用递归和许多集合,在其第一个元素上拆分参数内集合:lesserequal 和更大,在两者上递归并合并。合并排序的复杂性,搜索互联网。

【讨论】:

  • 我不认为你可以从一个集合中删除一个元素并将其插入另一个集合。
【解决方案3】:

RemoveAndAppend 在集合末尾追加?

好吧,如果这个方法有O(1) 似乎关键问题是如何在集合的未处理部分找到当前最大值 - 一旦最大值被删除并附加到末尾。

What is the best way to get the minimum or maximum value from an Array of numbers?

【讨论】:

    【解决方案4】:

    读取整个集合,在您的应用程序中对其进行排序,然后以正确的顺序“removeAndAppend”这些值(现在已知)。

    【讨论】:

      猜你喜欢
      • 2010-11-29
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多