基数排序赋值部分的运行时

Posted

技术标签:

【中文标题】基数排序赋值部分的运行时【英文标题】:Runtime for Assignment Part of Radix Sort 【发布时间】:2021-06-27 20:20:19 【问题描述】:

您如何描述以下代码的运行时分析?这是基数排序的第二步(第一步是创建计数器)。

   const reAssignArraySlots = (arr, counter) => 
      let i = 0;
      let j = 0;
      while(i<arr.length) 
        let k = 0;
        let num = counter[i] || 0;
        while(k<num) 
          arr[j] = i;
          k+=1;
          j+=1;
        
        i+=1;
        j+=1;
      
      return arr;
    ;

我相信无论如何都会是 O(n),但我想检查一下这种直觉。例子:

A) 所有元素都是相同的。计数器将是 '2': 3 。带有 i 的 while 循环将处理 1x,带有 k 的 while 循环将处理 3x,并且每次插入都是 O(1)。我将 3 次插入相加得到 O(3),即 O(n)

B) 所有元素都是独一无二的。计数器将是 '2': 1, '1': 1, '3': 1 。 while 循环将处理 i 3x。每次插入都是 O(1),加起来是 O(3),即 O(n)。

C) 非唯一的、非连续的元素。 '4':1,'1':1,'3':2。在这里我不确定。每次插入都会有 O(1),但我们会额外检查 i = 2,这不在此处。不确定这是否会使我们达到 O(4)。最终,如果我们有足够稀疏的东西,这可能会得到 O(n^2)。

代码的其余部分:

    const getCounter = (arr) => 
  const counter = ;
  let min, max;
  arr.forEach((item) => 
    if(counter[item] !== undefined) 
      counter[item] += 1;
     else 
      counter[item] = 1;
    
  );
  return counter;
;

export const countSort = (arr) => 
  const counter = getCounter(arr);
  return reAssignArraySlots(arr, counter);
;

【问题讨论】:

【参考方案1】:

我看到 2 个嵌套循环,所以我倾向于说它不比 O(n^2) 慢。

    i 在外循环中递增 k 在内部循环中递增(并在循环之前设置为零) j 在两个循环中都会递增

k 对于每个循环可能会有所不同,但可以说有一个平均值 ave_k 在循环结束时,在我看来j 将始终等于i * ave_k

最大的问题是k(或ave_k)的大小是多少?

它与i 成正比吗?那么你就有了 O(n^2)。 与ln(i)成正比吗?那么你就有了 O(n ln(n) )。 它是恒定的,独立于i吗?那么你就有了 O(n)。 它通常是i 的平方吗?那么你就有了 O(n^2) 它通常是i 的平方根吗?然后你有 O(n sqrt(n) )

【讨论】:

以上是关于基数排序赋值部分的运行时的主要内容,如果未能解决你的问题,请参考以下文章

基数排序和更改基数

4.10 基数排序

c中的基数排序算法[关闭]

算法渣-排序-基数排序

快速排序

在基数排序中需要帮助