计数排序的运行时间

时间:2013-03-21 12:02:17

标签: algorithm big-o asymptotic-complexity

我试图了解计数排序的运行时间。在我的笔记中,它说,假设数组A的大小是n,k是每个数字出现的次数,

 Counting-Sort(A,k) {
   for (i=1; i <= k; i++) // initialize number counters to 0
       times[i] = 0;

   for (j=1; j <= length[A]; j++) // decide how many times each
       times[A[j]]++;                  // number appears in the input

  // form the sorted array
  m=1;
    for ( i=1; i <= k; i++)    // consider each number in the range
         for ( j=1; j <= times[ i ]; j++) { // generate that number in 
            A[m]=i;                   // the output as many times as
            m++;                      // it occurs in the input
         }
  }
  

设t i 表示内循环针对每个i迭代的次数。当我们查看代码底部的嵌套for循环时,请注意,每次迭代内部循环时,我们都会在输出数组中的正确位置放置一个新数字。   因此:sum t i (从i = 1到k)= n。

我不明白为什么这个总和等于n。外循环迭代k次,内循环最多迭代n次,因此它必须是O(nk)。有人可以解释一下吗?感谢

3 个答案:

答案 0 :(得分:2)

<强>算法

计数排序,也称为直方图排序

n = length of input Array

k = number of unique symbols that appear in the input Array
  • 初始化需要k时间

  • 计数需要n时间

  • 枚举需要Sum { Count(i) } = n时间

<强>复杂性

Time = k + n + n = 2n+k

Time ~ O(2n+k) = O(n+k)

Space = n + k ~ O(n+k)

答案 1 :(得分:0)

这些说明并不完全正确。 k是数组中出现的最高数字(即数字从1到k)。那么,让我们逐步完成算法:

  1. 初始化k“垃圾箱”:O(k)
  2. 计算每个号码出现的频率:O(n)
    • 所有分档中的值总和恰好是n,因为这是我们在数组中总共有多少条目
  3. 迭代垃圾箱:O(k)
    • 在结果数组中设置与bin代表一样多的元素:貌似O(n)
  4. 这里重要的是我们知道即使我们遍历k个分区,也可能一般,最多{{1}由每个bin表示的值,我们设置了bin,这样,在外部循环的所有迭代中,内部循环仍然运行总共n次。因此,此步骤的总复杂度实际上为n

    如果我们忽略了关于垃圾箱内容的额外知识,那你就绝对正确。

    现在有一个最后的转折:如果O(n),它实际上在k > n而不是O(k)!因为现在外环是“经常运行”的东西。

    我希望这是有道理的。

答案 2 :(得分:0)

正如你所看到的那样循环

m=1;
for ( i=1; i <= k; i++)    // consider each number in the range
     for ( j=1; j <= times[ i ]; j++) { // generate that number in 
        A[m]=i;                   // the output as many times as
        m++;                      // it occurs in the input
     }

它的复杂性将等于内循环体执行的次数。 i = 1时,times[1] =&gt; i = 2时执行times[2]i = k次,times[k]times[1] + times[2] + ... + times[k]次,n次。因此,总体内体被执行{{1}}次,并且该总和等于{{1}},因为每个元素都被计算一次。