【问题标题】:Partial selection sort vs Mergesort to find "k largest in array"部分选择排序与合并排序以找到“数组中最大的 k”
【发布时间】:2014-11-17 20:55:19
【问题描述】:

我想知道我的思路是否正确。

我正在准备面试(作为一名大学生),我遇到的一个问题是在一个数组中找到 K 个最大的数字。

我的第一个想法是只使用部分选择排序(例如,从第一个元素开始扫描数组,并为看到的最低元素及其索引保留两个变量,并在数组末尾与该索引交换并继续这样做直到我们交换了 K 个元素并返回了该数组中前 K 个元素的副本)。 但是,这需要O(K*n) 时间。如果我简单地使用 Mergesort 之类的高效排序方法对数组进行排序,则只需 O(n*log(n)) 时间即可对整个数组进行排序并返回 K 个最大的数字。

在面试期间讨论这两种方法是否足够好(比较输入的 log(n) 和 K,并使用两者中较小的一个来计算最大的 K)或者假设我是否安全? m 期望给出这个问题的 O(n) 解?

【问题讨论】:

    标签: algorithm sorting big-o


    【解决方案1】:

    存在一个O(n) algorithm for finding the k'th smallest element,一旦你有了那个元素,你就可以简单地浏览列表并收集适当的元素。它基于 Quicksort,但其工作原理背后的原因相当复杂......还有一个更简单的变体 可能 将在 O(n) 中运行。 My answer to another question 包含对此的简短讨论。

    【讨论】:

      【解决方案2】:

      以下是通过谷歌搜索发现的这个特定面试问题的一般性讨论:

      http://www.geeksforgeeks.org/k-largestor-smallest-elements-in-an-array/

      至于你关于面试的一般问题,可能很大程度上取决于面试官。他们通常喜欢看看你对事情的看法。所以,只要你能想出一些初步的解决方案,你的面试官很可能会从那里提出问题,具体取决于他们到底在寻找什么。

      【讨论】:

        【解决方案3】:

        恕我直言,如果面试官说数据集很大(比如十亿个元素),我认为他不会对这两种方法感到满意。在这种情况下,如果要返回的K 很大(接近十亿),您的部分选择几乎会导致O(n^2)。我认为这完全取决于所提出问题的复杂性。

        编辑:Aasmund Eldhuset 的回答向您展示了如何实现 O(n) 时间复杂度。

        【讨论】:

        • 是的,你可以。请参阅 Aasmund 的回答。
        • @StefanoSanfilippo 会给我们kth 最大/最小数字,但不是k 最大/最小数字s
        • @noMAD:一旦你有了那个元素,你只需扫描列表并收集小于或等于kth 最小元素的元素。您还需要处理可能存在多个同样小的元素的事实,但您仍然可以在线性时间内完成。
        【解决方案4】:

        如果你想找到 K(所以对于 K = 5,你会得到五个结果 - 五个最高的数字)那么你能得到的最好的结果是 O(n+klogn) - 你可以在 O(n) 中建立优先队列,然后调用pq.Dequeue() k 次。如果您正在寻找 K 最大的 数字,那么您可以通过 O(n) 快​​速排序修改获得它 - 它称为 k-th order statistics。伪代码如下所示:(它是随机算法,平均时间约为O(n),但最坏的情况是O(n^2)

        QuickSortSelection(numbers, currentLength, k) {
            if (currentLength == 1)
              return numbers[0];
            int pivot = random number from numbers array;
        
            int newPivotIndex = partitionAroundPivot(numbers) // check quicksort algorithm for more details - less elements go left to the pivot, bigger elements go right
        
            if ( k == newPivotIndex )
                return pivot;
            else if ( k < newPivotIndex )
                return QuickSortSelection(numbers[0..newPivotIndex-1], newPivotIndex, k)
            else
               return QuickSortSelection(numbers[newPivotIndex+1..end], currentLength-newPivotIndex+1, k-newPivotIndex);
        }
        

        正如我所说,这个算法是O(n^2) 最坏的情况,因为枢轴是随机选择的(但是~n^2 的运行时间概率类似于1/2^n)。您可以使用例如median of three median 作为基准将其转换为具有相同运行时间最坏情况的确定性算法 - 但在实践中它较慢(由于常数)。

        【讨论】:

          猜你喜欢
          • 2018-04-19
          • 2018-12-16
          • 1970-01-01
          • 1970-01-01
          • 2016-03-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多