【问题标题】:Most efficient way to sort a unique, bounded array?对唯一的有界数组进行排序的最有效方法?
【发布时间】:2021-06-01 16:27:50
【问题描述】:

我认为这是重复的,但我找不到。

假设我们有一个数组,我们知道每个值都是唯一的,并且每个值都在一个范围之间。例如,假设我们知道数组由 0 到 100 之间的唯一值组成。示例:

[ 5, 46, 15, 83, 55, 28 ]

然后我想将此数组排序为以下内容:

[ 5, 15, 28, 46, 55, 83 ]

显然我可以只使用快速排序或任何其他比较排序,但那将是O(n log n)。也存在非比较排序,例如基数排序、桶排序、计数排序等,但据我所知,这些排序都没有保持值必须唯一的约束。

通常情况下,您允许的约束越多,您的算法就越高效。是否有任何算法对唯一的有界数组更有效?如果不是,哪种非比较排序算法对这种类型的数据集最有效?

【问题讨论】:

  • 我不知道使用什么算法对键进行排序,但Object.keys( arr.reduce( (o,v) => { o[ v ] = null; return o; }, {} ) ) 可能值得一试。

标签: javascript arrays performance sorting unique


【解决方案1】:

鉴于唯一值的约束和有限范围,您可以声明一个长度足以容纳给定范围内的每个唯一整数的数组,然后您可以执行特殊情况的桶排序,其中每个桶总是能够包含唯一值,最后过滤数组以删除剩余的空槽。与其他非比较排序算法一样,这种方法是 O(n) 渐近时间复杂度。

const input = [5, 46, 15, 83, 55, 28];

function sort(unsorted, lower, upper) {
  const sorted = Array(upper - lower);

  for (let i = 0; i < unsorted.length; ++i) {
    sorted[unsorted[i] - lower] = unsorted[i];
  }

  return sorted.filter(() => true);
}

const output = sort(input, 0, 100);

console.log(output);

【讨论】:

  • 啊,我明白了。不幸的是,这仍然比插入排序慢,因为我的列表不是很大(只是进行了基准测试),但我认为它在技术上确实具有更好的时间复杂度。如果没有其他更快的方法出现,我想我会继续使用插入排序并接受这个答案,因为它在技术上是我问题的答案。
  • @RyanPeschel 是的,对于小列表,插入排序往往非常快。除非 n 的值非常大(即 > 1000000),否则渐近时间复杂度无关紧要
  • 是的,在发布此内容并同时进行搜索后,我意识到这一点。好吧,如果来的人确实有一个很大的清单,那么这个答案可能会对他们有所帮助。
  • 这不是计数排序的变体吗?
【解决方案2】:

类似的东西?

const arr1 = [ 5, 46, 15, 83, 55, 28  ]

const  min = Math.min( ...arr1)

const res = []
for(let v of arr1) res[v-min] = v
for(let i=res.length;i--;) if (res[i]===undefined) res.splice(i, 1)

console.log( res )
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案3】:

    我建议进行计数排序,但是使用一个字节数组来进行通常的计数,因为计数值只会是 0 或 1,因为要排序的数组具有唯一值。这也适用于没有值出现超过 255 次的数组(因此每个计数仍然适合无符号字节)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-01
      • 2016-10-19
      • 2010-11-07
      • 2022-01-18
      相关资源
      最近更新 更多