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

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

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

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

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

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

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

程序员面试题精选100题(57)-O(n)时间的排序[算法]相关推荐

  1. 程序员面试题精选100题(20)-最长公共子串[算法]

    题目:如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,则字符串一称之为字符串二的子串.注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中.请编写一个函数,输入两个字符串, ...

  2. 程序员面试题精选100题(42)-旋转数组的最小元素[算法]

    题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个排好序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的 ...

  3. 程序员面试题精选100题(44)-数值的整数次方[算法]

    题目:实现函数double Power(double base, int exponent),求base的exponent次方.不需要考虑溢出. 分析:这是一道看起来很简单的问题.可能有不少的人在看到 ...

  4. 程序员面试题精选100题(43)-n个骰子的点数[算法]

    题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为S.输入n,打印出S的所有可能的值出现的概率. 分析:玩过麻将的都知道,骰子一共6个面,每个面上都有一个点数,对应的数字是1到 6之间的一个数字. ...

  5. 程序员面试题精选100题:41-50解题报告

    程序员面试题精选100题(41)-把数组排成最小的数[算法]   题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个.例如输入数组{32,  321},则输出这两个能 ...

  6. 程序员面试题精选100题

    程序员面试题精选100题(01)-把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向. 比如将二元查找树   ...

  7. [程序员面试题精选100题]13.第一个只出现一次的字符

    [题目] 在一个字符串中找到第一个只出现一次的字符.如输入abaccdeff,则输出b. [分析] [代码] /********************************* * 日期:2013- ...

  8. 程序员面试题精选100题(51)-顺时针打印矩阵

    // 程序员面试题精选100题(51)-顺时针打印矩阵.cpp : 定义控制台应用程序的入口点. //#include "stdafx.h" #include <iostre ...

  9. 程序员面试题精选100题:求从1到n的正数中1出现的次数

    // 程序员面试题精选100题(25):求从1到n的正数中1出现的次数 // 如 f(253) = (2!=0) * 100 + 2 * f(99) + (5!=0) * 10 + 5 * f(9) ...

最新文章

  1. 网页制作的中的一些工具代码
  2. python中nlp的库_单词袋简介以及如何在Python for NLP中对其进行编码
  3. Word中更新交叉引用
  4. JavaScript实现breadth First Search广度优先搜索算法(附完整源码))
  5. html不继承父级背景色,javascript – 如何获取从父元素继承的计算背景颜色样式...
  6. [JavaWeb-MySQL]DDL_操作数据库,表
  7. python 替换文本 通配符_使用通配符搜索和替换文本文件中的字符串
  8. mysql 变量被引号括住_【已解决】mysql中操作表的字段名时是否一定要用反引号括起来...
  9. 用 Ansible 实现基于 OpenShift (Kubernetes) 的 DevOps
  10. JavaEE——Mybatis(5)--resultMap自定义结果集封装
  11. usb无线网卡安装在服务器上,USB无线网卡怎么用?USB无线网卡如何安装?
  12. bigdecimal负数变正数_Java中BigDecimal的8种舍入模式
  13. glusterfs:Server-quorum和Client Quorum
  14. 某厂机试算法刷题一览
  15. realme 拨号代码_手机拨号界面为什么会有quot;*和#quot;键?这2个键有什么用?望周知...
  16. npoi 设定视图为分页预览_NPOI导出EXCEL 打印设置分页及打印标题
  17. css布局:table布局、两栏布局、三栏布局
  18. 2019年的元旦还是一个人?邮箱163陪你如何?
  19. JQuery实现图片自动轮播左右切换鼠标移入
  20. HTML常用标签、文本格式化标签:加粗、倾斜、删除线、下划线等

热门文章

  1. 李开复:天才将占领创业领域
  2. 深入理解分布式技术 - 缓存高可用
  3. Java 8 - 正确高效的使用并行流
  4. Oracle-PROCEDURE权限解读
  5. C语言结构体指针与结构体变量作形参的区别
  6. c++ 遍历所有点且距离最短_L3图论第08课 图的遍历
  7. oracle测试表什么名字,Oracle_PLSQL测试题与答案(绝对经典)
  8. SpringBoot 源码解析 (一)----- SpringBoot核心原理入门
  9. 华为云服务的购买和建站
  10. python入门之函数调用第二关_猪行天下之Python基础——5.1 函数(上)