如何按大小

时间:2015-11-02 09:12:53

标签: algorithm sorting complexity-theory

我有 n 不同的数字,我想将它们分类为 k 组,这样第1组中的任何数字都小于第2组中的任何数字,任何人第2组比第3组中的任何人小,依此类推,直到组 k (数字不必在每组内分类)。我要求设计一个在 O(n log k)中运行的算法,但我只能提出 O(n ^ 2)。< / p>

我该怎么做?

4 个答案:

答案 0 :(得分:2)

您可以通过修改Bucket排序算法来实现这一点,下面我已经包含了一个JavaScript实现,有关源代码的更多详细信息,请参阅Github。此实现使用16个桶,您必须修改它以允许k桶,您可以省略桶本身的排序。一种方法是使用2^p桶,其中p是满足2^p < n的最小整数。该算法将在 O(n log k)

中运行

&#13;
&#13;
// Copyright 2011, Tom Switzer
// Under terms of ISC License: http://www.isc.org/software/license

/**
 * Sorts an array of integers in linear time using bucket sort.
 * This gives a good speed up vs. built-in sort in new JS engines
 * (eg. V8). If a key function is given, then the result of
 * key(a[i]) is used as the integer value to sort on instead a[i].
 *
 * @param a A JavaScript array.
 * @param key A function that maps values of a to integers.
 * @return The array a.
 */
function bsort(a, key) {
  key = key || function(x) {
    return x
  };
  var len = a.length,
    buckets = [],
    i, j, b, d = 0;
  for (; d < 32; d += 4) {
    for (i = 16; i--;)
      buckets[i] = [];
    for (i = len; i--;)
      buckets[(key(a[i]) >> d) & 15].push(a[i]);
    //This implementation uses 16 buckets, you will need to modify this
    for (b = 0; b < 16; b++)
      //The next two lines sort each bucket, you can leave it out
      for (j = buckets[b].length; j--;)
        a[++i] = buckets[b][j];
  }
  return a;
}


var array = [2, 4, 1, 5, 3];

$('#result').text(bsort(array, function(x) {
  return x
}));
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"></div>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

请注意,问题陈述是将n 个不同的数字分成k个组。如果下面的wiki链接中有重复项,这会变得更复杂。

任何能够确定具有小于O(n log(k))复杂度的第k个最小元素的过程可以使用k-1次来产生对应于k个组之间的边界的元素的阵列。然后可以在阵列上进行单次传递,对边界阵列进行二进制搜索,以将阵列分成具有O(n log(k))复杂度的k组。但是,似乎至少有一个找到第k个最小元素的算法也会对数组进行分区,因此可以单独使用它来创建k个组。

使用具有最差情况时间O(n)的选择算法的无序部分排序是可能的。维基链接:

http://en.wikipedia.org/wiki/Selection_algorithm

http://en.wikipedia.org/wiki/Selection_algorithm#Unordered_partial_sorting

http://en.wikipedia.org/wiki/Quickselect

http://en.wikipedia.org/wiki/Median_of_medians

http://en.wikipedia.org/wiki/Soft_heap#Applications

答案 2 :(得分:1)

使用来自QuickSort的分区函数的K选择算法 - QuickSelect 为简单起见,让K为2的幂 在第一阶段,我们对N个元素进行分区,它需要O(N)〜p * N时间,其中p是一些常数 在第二阶段,我们递归地制作2个N / 2个元素的分区,它需要2 * p * N / 2 = p * N时间。
在第三阶段,我们制作4个N / 4个元素的分区,需要4 * p N / 4 = p N时间。
...
在最后阶段,我们制作N个K元素的K个分区,它需要K * p * N / K = p * N时间。

注意有Log(K)阶段,因此总时间为Log(K)* p * N = O(N * Log(K)

答案 3 :(得分:0)

感谢您的帮助,基本上是一个快速选择(或任何线性时间排序算法,在线性时间内找到第k个统计量就足够了),并且在运行k-1次之后,我们对其进行二元搜索原始数组将元素拆分成组,得到O(nlog k)。

此外,如果您不想进行二元搜索,在quickselect中,您还可以分离元素并在每个子集中查找统计信息! @rcgldr,@ MBo谢谢你的想法!