`
mmdev
  • 浏览: 12950706 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

时间复杂度为O(n)的排序

 
阅读更多

题目:某公司有几万名员工,请完成一个时间复杂度为O(n)的算法对该公司员工的年龄作排序,可使用O(1)的辅助空间。

分析:排序是面试时经常被提及的一类题目,我们也熟悉其中很多种算法,诸如插入排序、归并排序、冒泡排序,快速排序等等。这些排序的算法,要么是O(n2)的,要么是O(nlogn)的。可是这道题竟然要求是O(n)的,这里面到底有什么玄机呢?

题目特别强调是对一个公司的员工的年龄作排序。员工的数目虽然有几万人,但这几万员工的年龄却只有几十种可能。上班早的人一般也要等到将近二十岁才上班,一般人再晚到了六七十岁也不得不退休。

由于年龄总共只有几十种可能,我们可以很方便地统计出每一个年龄里有多少名员工。举个简单的例子,假设总共有5个员工,他们的年龄分别是2524262425。我们统计出他们的年龄,24岁的有两个,25岁的也有两个,26岁的一个。那么我们根据年龄排序的结果就是:2424252526,即在表示年龄的数组里写出两个24、两个25和一个26

想明白了这种思路,我们就可以写出如下代码:

void SortAges(int ages[], int length)

{

if(ages == NULL || length <= 0)

return;

const int oldestAge = 99;

int timesOfAge[oldestAge + 1];

for(int i = 0; i <= oldestAge; ++ i)

timesOfAge[i] = 0;

for(int i = 0; i < length; ++ i)

{

int age = ages[i];

if(age < 0 || age > oldestAge)

throw new std::exception("age out of range.");

++ timesOfAge[age];

}

int index = 0;

for(int i = 0; i <= oldestAge; ++ i)

{

for(int j = 0; j < timesOfAge[i]; ++ j)

{

ages[index] = i;

++ index;

}

}

}

在上面的代码中,允许的范围是099岁。数组timesOfAge用来统计每个年龄出现的次数。某个年龄出现了多少次,就在数组ages里设置几次该年龄。这样就相当于给数组ages排序了。该方法用长度100的整数数组辅助空间换来了O(n)的时间效率。由于不管对多少人的年龄作排序,辅助数组的长度是固定的100个整数,因此它的空间复杂度是个常数,即O(1)

本文已经收录到《剑指Offer——名企面试官精讲典型编程题》一书中,有改动,书中的分析讲解更加详细。欢迎关注。

博主何海涛对本博客文章享有著作权。网络转载请注明出处http://zhedahht.blog.163.com/。整理出版物请和作者联系。对解题思路有任何建议,欢迎在评论中告知,或者加我微博http://weibo.com/zhedahht或者http://t.163.com/zhedahht与我讨论。谢谢。

分享到:
评论

相关推荐

    实现了7种排序算法.三种复杂度排序.三种nlogn复杂度排序(堆排序,归并排序,快速排序)一种线性复杂度的排序.zip

    直接插入排序的时间复杂度为O(n^2),其中n是待排序元素的数量。这是因为对于每个待插入元素,都需要进行至多n-1次比较。直接插入排序的空间复杂度为O(1),因为它不需要额外的存储空间。此外,直接插入排序是稳定的,...

    一种O_n_nlog_2m_时间复杂度的排序算法.pdf

    一种O_n_nlog_2m_时间复杂度的排序算法.pdf

    基数排序,快于sort的O(n)排序

    时间复杂度达到O(n)的不同于sort给予比较的O(nlogn)排序,是基于计数的一种线性排序方法,效率非常优秀。

    时间复杂度的一些相关资源

    例如,在排序算法中,冒泡排序的时间复杂度为O(n^2),而快速排序的时间复杂度在平均情况下为O(nlogn),因此在处理大规模数据时,快速排序通常比冒泡排序更高效。 总之,时间复杂度是评估算法效率的重要工具,它帮助...

    时间复杂度大小比较.doc

    一般情况下,时间复杂度用大写O和一个函数f(n)来表示,记作O(f(n)),其中n是输入数据的规模。这个函数f(n)可以是常数、对数、线性、线性对数、二次、指数等。 常见的时间复杂度从低到高排序如下: O(1):常数时间...

    根号n段归并排序算法

    根号n段归并排序算法的C++代码实现: 1.合并【根号n向下取整】段子数组,使用了自底向上的两两合并策略。 2.算法的总体时间复杂度为nlogn 3.带有详细注释

    时间复杂度大小比较,用python举例

    O(nlogn):表示算法的执行时间既随n的增大而增长,又随logn的增大而增长,通常出现在一些高效的排序算法中,如归并排序。 O(n²)、O(n³):表示算法的执行时间随输入规模n的平方或立方增长,通常出现在嵌套循环等...

    算法设计与分析-1排序算法性能分析-冒泡/选择/插入/合并/快速排序-pre ppt

    算法设计与分析 一PRESETATION 仅做参考,请勿copy冲查重塔峰 排序算法性能分析 ...但注意理论上快速排序的空间复杂度较高为O(n),且最坏情况时时间复杂度也达到了O(n2)。所以快速算法也较为常用。

    基数排序及流程图

    时间效率:待排序列为n个记录,10个关键码,关键码的取值范围为0-9,则进行链式基数排序的时间复杂度为O(4(n+10)),其中,一趟分配时间复杂度为O(2(n+10),一趟收集时间复杂度为O(2(n+10),共进行2趟分配和收集。

    selectionsort:时间复杂度为 O(n^2) 的选择排序

    基于时间复杂度为 O(n^2) 的。 安装 $ npm install --save selectionsort 用法 var selectionsort = require ( 'selectionsort' ) ; selectionsort ( [ 6 , 4 , 9 , 3 , 1 , 7 ] ) ; // =&gt; [1,3,4,6,7,9] ...

    数据结构实验报告11-内部排序-三种平均时间复杂度为O(nlogn)的内部排序算法的实现-实验内容与要求.docx

    输入n个整数,用快速排序、堆排序与2路归并排序算法实现由小到大排序并输出排序结果。要求排序数据及排序结果用字符文件实现输入与输出。

    一维数组排序标程

    一维数组排序标程,绝对AC,时间复杂度O(n logn),解压密码:JYQJYQFUCKYOU

    数据结构练习题.docx

    1-4在任何情况下,时间复杂度为O(n​2​​) 的算法比时间复杂度为O(n*logn)的算法所花费的时间都长。F 1-5对n个整数排序,在最坏的情况下,不能保证以少于O(n)的时间完成。T 1-6用渐进表示法分析算法复杂度的增长...

    python实现冒泡排序

    冒泡排序的时间复杂度为O(n^2),其中n是待排序数组的长度。 冒泡排序的基本思想是通过多次比较和交换,将最大的元素逐渐“冒泡”到数组的末尾。在每一轮的比较中,如果前一个元素大于后一个元素,则进行交换。通过...

    [c++基础算法] 归并排序

    归并排序的时间复杂度是O(n㏒n)。 假设被排序的数列中有N个数。遍历一趟的时间复杂度是O(N),需要遍历多少次呢? 归并排序的形式就是一棵二叉树,它需要遍历的次数就是二叉树的深度,而根据完全二叉树的可以得出它的...

    八大排序算法总结(含代码)

    当n较大,则应采用时间复杂度为O(nlogn)的排序方法:快速排序、堆排序或归并排序。 时间复杂度:冒泡排序=选择排序=插入排序=O(N的平方);其他都是O(NlogN),但是并不是绝对的。 详细内容请见文档。

    python冒泡排序.md

    冒泡排序的时间复杂度为O(n^2),其中n是列表的长度。这是因为对于每个元素,我们可能需要与其后面的所有元素进行比较和交换。尽管冒泡排序在某些情况下可能不是最优的选择,特别是当处理大型数据集时,但它易于理解...

    数据结构课程设计——数排序及树的遍历

    这种方法在n个元素进行排序时,最坏的情况下要移动元素的次数是[n(n-1)]/2次,即时间复杂度是O(n2);在插入第n+1个数时最坏情况下要移动n个元素,删除一个数时,最坏情况下时间复杂度也是O(n)。插入和删除一个...

Global site tag (gtag.js) - Google Analytics