获取第N小的值
template <class value_t>
int partition(value_t *arr, int first, int last)
{
--last;
int i = first - 1;
int x = arr[last];
for(int j = 0; j < last; ++j)
{
if(arr[j] <= x)
++i, std::swap(arr[j], arr[i]);
}
std::swap(arr[i + 1], arr[last]);
return i + 1;
}
template <class value_t>
int GetNthLeast(value_t* arr, int first, int last, int nth)
{
assert(nth <= last);
int pivot = partition(arr, first, last);
if(pivot + 1 == nth)
return arr[pivot];
if(pivot + 1 < nth)
GetNthLeast(arr, pivot + 1, last, nth);
else
GetNthLeast(arr, first, pivot, nth);
}
直接看上去,上面的代码貌似在last-first为0的时候,也会运行,实际上并不是如此。如果序列为0,说明上次是一个极差的划分,如果要找的元素不在povit上,那么它也一定不会在0区间里面。比如说,N长度的序列,被划分为[0,N),和[N+1,……],这样的区间。第二个区间是空的,那么找到的array[N]就是第N小的值,而且其左边的区间,也就是[0,N)里面的值都比它要小。如果要找比array[N]大的值,是找不到的,因为此时的array[N]已经是最大的值。在N长度的序列中找第N+1小的值,显然是不现实的(或者报错,或者返回第N小的值)。
下面来看一下算法的时间复杂度。当每次划分都是最糟时,一共需要n次划分,每次划分的复杂度为O(N),因此为O(N^2)。
在一般情况下,计算它的期望复杂度,如下图:

因此,平均情况下,任何的顺序统计量都可以在线性时间得到。
浙公网安备 33010602011771号