给定一个n个数的数组,其中的每个元素都小于n的平方,请设计一个时间复杂度为O(n)的排序算法

2025-01-01 11:06:47
推荐回答(1个)
回答1:

可以考虑用计数排序的思想来实现这点,用空间换时间。

其中用A[n]数组代表原始数组,B[n]代表升序排序后的数组,C[n*n]数组用于计数,C[i]值代表小于等于i的元素个数,那么每一次输出排序后的B[i]时,便有B[--C[i]]=i,只是问题中元素的取值范围是n^2以内的,因此造成了这一方法的时间复杂度无形中升至了n^2,但事实上其时间复杂度可以随数据元素范围减小而降低至线性时间内,思想就是空间换取时间,并且只适用于正整数的排序。

#include
#define n 10
using namespace std;

int A[n];
int B[n];
int C[n*n];

int main()
{
int nTest;
int i;
cin>>nTest;
while( nTest-- ){
for( i=0 ; i cin>>A[i];

memset( C,0,sizeof(C) );
for( i=0 ; i C[A[i]]++;

for( i=1 ; i C[i]+=C[i-1];

for( i=0 ; i B[C[A[i]]-1]=A[i];
C[A[i]]--;
}
for( i=0 ; i cout< cout<
}
return 0;
}
/*
1
31 77 37 77 37 77 37 77 37 99
31 37 37 37 37 77 77 77 77 99
*/

--------------------------------------------------------
回答补充:
对,正是你想的那样,正因为待排序的数据范围上界达到了n^2的数量级,导致在这个问题中计数排序的效率下降了。
但是,试想一下,上界若不是一个很大的数,举个例子,待排序的数据量n=10^8,而数据范围上界m=10^5,那么按照正常的排序方法时间效率的最低下界为o(nlog(n)),当n=10^8时也是很大的时间开销。而对计数排序而言,此时的时间开销仅仅是o(n),即用于更新数组C[m+1]上了,可以算是在线性时间内完成排序的。