这是一个使用Quicksort分区算法在n个元素数组中找到第k个最小数的算法。
small(a,i,j,k)
{
if(i==j) return(a[i]);
else
{
m=partition(a,i,j);
if(m==k) return(a[m]);
else
{
if(m>k) small(a,i,m-1,k);
else small(a,m+1,j,k);
}
}
}
其中i,j是数组的起始和结束索引(j-i = n(数组中元素的数量)),k是最小的第k个,无法找到。 我想知道什么是最好的情况,以及上述算法的平均情况以及简要说明。我知道我们不应该在最好的情况下计算终止条件,并且分区算法也需要O(n)。我不希望渐近符号,但如果可能的话,我想要精确的数学结果。
答案 0 :(得分:2)
首先,我假设数组已经排序 - 你没有提到 - 因为该代码不会起作用。而且,这对我来说就像常规的二元搜索一样。
总之...
最好的情况是当数组是一个元素长(你因为i == j而立即返回),或者对于大的n值,如果中间位置m与k相同;在这种情况下,不会进行递归调用,也会立即返回。这最好是O(1)。
对于一般情况,考虑T(n)表示使用算法解决大小为n的问题所花费的时间。我们知道:
T(1)= c
T(n)= T(n / 2)+ c
其中c是恒定时间操作(例如,如果i与j相同则比较时间等)。一般的想法是,为了解决大小为n的问题,我们消耗一些恒定时间c(以决定m == k,如果m> k,计算m等),然后我们消耗所花费的时间解决了一半大小的问题。
扩展重复可以帮助你推导出一个通用公式,虽然这很直观,这是O(log(n)):
T(n)= T(n / 2)+ c = T(n / 4)+ c + c = T(n / 8)+ c + c + c = ... = T(1)+ c * log(n)= c *(log(n)+ 1)
这应该是确切的数学结果。该算法在O(log(n))时间内运行。平均案例分析更难,因为您需要知道算法的使用条件。阵列的典型大小是多少? k的典型大小?数组中k的最小位置是什么?例如,如果它在中间,则平均情况可以是O(1)。这实际上取决于你如何使用它。