我试图了解计数排序的运行时间。在我的笔记中,它说,假设数组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)。有人可以解释一下吗?感谢
答案 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)。那么,让我们逐步完成算法:
k
“垃圾箱”:O(k)
O(n)
n
,因为这是我们在数组中总共有多少条目O(k)
O(n)
这里重要的是我们知道即使我们遍历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}},因为每个元素都被计算一次。