Processing math: 0%

浅谈计数排序

所谓计数排序,就是建立在计数上的排序。

计数排序不以比较为基础,所以可以打破比较排序O(nlogn)的复杂度下界。

我们只要计算出比i小的数字有多少个,就可以知道i在数据里的排名。然后根据排名,我们就可以反造一波排好序的数据了。

我们用rk[i]记录第i个数据的排名,sum[i]记录权值1~i一共有多少个数据。然后a[i]的排名就是sum[a[i]],如果有相同的权值那么每次用sum[a[i]]更新一个数据的rk后都要把sum[a[i]]--。

那么根据ans[rk[i]]=a[i],一个一个把数据往ans数组里填就是了。

时间复杂度:O(n+maxv)

空间复杂度:O(n+maxv)

代码如下:

#include <cstdio>
using namespace std;

const int maxn=1e6+5;

int n,rk[maxn];
int a[maxn],b[maxn],sum[maxn];

int read() {
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

int main() {
	n=read();
	for(int i=1;i<=n;i++)
		a[i]=read(),sum[a[i]]++;
	for(int i=1;i<=n;i++)
		sum[i]=sum[i]+sum[i-1];//利用前缀和求sum
	for(int i=1;i<=n;i++)
		rk[i]=sum[a[i]]--;//求rk[i]
	for(int i=1;i<=n;i++)
		b[rk[i]]=a[i];//求rk的反数组
	for(int i=1;i<=n;i++)
		printf("%d ",b[i]);//rk的反数组就是排好序的数据
	return 0;
}
posted @   AKMer  阅读(353)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示