时间为O(n)排序——计数排序
来源:互联网 发布:golub 矩阵计算 pdf 编辑:程序博客网 时间:2024/06/05 14:43
【题 目】某公司有几万名员工,请完成一个时间复杂度为O(n)的算法对该公司员工的年龄进行排序,可以使用O(1)的辅助空间。
【思 路】在数据结构和算法的学习中,排序肯定是重中之重,然而仔细回想我们学习过的排序算法,无论是冒泡排序,归并排序,插入排序,希尔排序,甚至著名的快速排序,时间复杂度都达不到O(n),这些算法的时间复杂度要么为O(n2),要么为O(nlogn),然而这道题却要求我们用O(n)的时间复杂度排序,到底是什么原因呢?
通过简单的思考,我们发现,员工虽然有几万名,但是要排序的年龄却不是只有几万种,我们考虑一个人正常的工作年龄22——60岁,再发到范围也不过0——99岁(夸张了点),那也只有100个数字,换句话说,我们要排序不是几万个数字,而只是几万个重复出现在区间『0,100』的数字。这样,我们容易想到,我们用一个年龄的计数器数组来记录没一个年龄出现了多少次,age[24]表示年龄为24的员工人数。对全部员工做完如此的统计工作后,我们就可以按照这个数组来进行简单的“数数”工作就行了。
具体的代码如下:
1 #include<iostream> 2 #include<string> 3 #include<ctime> 4 #include<cstdlib> 5 #define random(x) (rand()%x) 6 using namespace std; 7 8 void SortAges(int employeeAge[],int length) 9 {10 //无效输入11 if(employeeAge == NULL || length < 0)12 return;13 14 //计数器数字age[],定义,初始化15 const int maxAge = 99;16 int age[maxAge + 1];17 for(int i = 0;i <= maxAge;++i)18 {19 age[i] = 0;20 }21 22 //计算器数组统计每个年龄出现的次数23 for(int j = 0;j < length;++j)24 {25 int tempage = employeeAge[j];26 if(tempage < 0 || tempage > maxAge)27 {28 cout<<"ERROR:the age is not in the valid range!"<<endl;29 }30 31 age[tempage]++;32 }33 34 //根据计数器数组重新排列“员工年龄”数组的顺序35 int index = 0;36 for(i = 0;i <= maxAge;++i)37 {38 for(int j = 0;j < age[i];++j)39 {40 employeeAge[index] = i;41 index++;42 }43 }44 }45 46 int main()47 {48 //定义员工年龄数组,随机赋值[0.99]49 int empAge[100];50 srand((int)time(0));51 for(int i = 0;i < 100;++i)52 {53 empAge[i] = random(100);54 }55 56 cout<<"the original age list is:"<<endl;57 for(i = 0;i < 100;++i)58 {59 cout<<empAge[i]<<"\t";60 //if((i + 1) % 20 == 0)61 //cout<<endl;62 }63 64 SortAges(empAge,100);65 66 67 cout<<"******************************************************************************"<<endl;68 cout<<"the sorted age list is:"<<endl;69 for(i = 0;i < 100;++i)70 {71 cout<<empAge[i]<<"\t";72 //if((i + 1) % 20 == 0)73 //cout<<endl;74 }75 76 return 0;77 78 }
为简便起见,笔者设公司只有100个员工,每个员工的年龄取[0,99]之间的随机数,得到程序的运行情况如下:
反思:该算法用长度为100的定长度作为“过渡”,首相将要排序的数组进行统计,统计结果用定长数组(即前面提到的计数器数组)存储,然后对定长数组“数数”,然后将结果写入原来需要排序的数组,由于不管员工的数量N为多大(几万,十几万),所需要的数组长度都为100,因为年龄的是受限范围为[0,99]获得了时间复杂度为O(n)的排序算法,也算是用空间换取时间了。
Reference:
时间为O(n)的排序:http://zhedahht.blog.163.com/blog/static/25411174201131184017844/
注:
1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。
2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。
- 时间为O(n)排序——计数排序
- O(n)时间的排序---计数排序
- 时间复杂度为O(n)的排序算法--计数算法
- 复杂度为o(n)的计数排序
- 【排序】时间复杂度为O(N^2)的排序——冒泡、选择和插入排序
- O(N)时间复杂度的排序算法-计数排序
- 号称效率为O(n)的排序算法-----计数排序
- 时间复杂度为O(n)的排序
- 时间为O(n)的排序方法
- 时间复杂度为O(n)的排序
- 计数排序(O(n))
- 计数排序详解:O(n)
- 1~n无序数组时间复杂度为O(n)排序
- 1~n无序数组时间复杂度为O(n)排序
- 计数排序——O(n)复杂度基于非比较的排序方法
- 计数排序;非比较排序法;时间复杂度接近于O(n);
- 计数排序,传说中时间复杂度O(n+k)的排序算法
- 计数排序:时间复杂度O(n+k),空间复杂度O(k)
- VC中自画控件的过程和方法(CButton, CEdit, etc)
- zoj1001
- os NSNumber NSDate Usage
- [技巧]怎样用WinRAR解压7z.001,7z.002……格式的文件
- C#动态绑定Menu控件
- 时间为O(n)排序——计数排序
- 手电可以这么玩!一个牛逼的光电涂鸦作品!当手电筒遇到了单反相机,于是不可思议的一幕发生了。。
- 跳台阶问题
- 后缀数组简单总结
- activiti Demo Setup 安装
- Linux入门:内存测试工具(Memtest86+)
- 打tar包以及压缩及解压
- Java中建立自己的包
- 算法之道—形而之上谓之道