53. 特殊的O(n)时间排序[sort ages with hashtable]

【本文链接】

http://www.cnblogs.com/hellogiser/p/sort-ages-with-hashtable.html

题目】

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

分析

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

题目特别强调是对一个公司的员工的年龄作排序。员工的数目虽然有几万人,但这几万员工的年龄却只有几十种可能,因此想到可以通过使用Hash表来辅助排序。由于年龄总共只有几十种可能,我们可以很方便地统计出每一个年龄里有多少名员工。举个简单的例子,假设总共有5个员工,他们的年龄分别是25、24、26、24、25。我们统计出他们的年龄,24岁的有两个,25岁的也有两个,26岁的一个。那么我们根据年龄排序的结果就是:24、24、25、25、26,即在表示年龄的数组里写出两个24、两个25和一个26。

【代码】

C++
Code






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

 

// 53_SortAges.cpp : Defines the entry point for the console application.

//
/*
     version: 1.0

     author: hellogiser

     blog: http://www.cnblogs.com/hellogiser

     date: 2014/5/24
*/


#include "stdafx.h"
#include <iostream>
#include <ctime>
using namespace std;
#define MAX 10
#define OLDEST 99

int ages[MAX];

// init ages

void InitAges(int *ages, int n)

{
     srand(time(NULL));

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

         ages[i] = rand() % 100;

}

// print ages
void PrintAges(int *ages, int n)

{
    if(NULL == ages || n <= 0)

        return;
    for (int i = 0; i < n; ++i)

         printf("%d ", ages[i]);

     printf("\n");
}

// sort ages in O(n)

void SortAges(int *ages, int n)

{
    if(NULL == ages || n <= 0)

        return;
    int timesOfAge[OLDEST + 1];
    // init times to 0

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

         timesOfAge[i] = 0;

    // get age times

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

     {

        int age = ages[i];

        if(age <= 0 || age > 100)

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

         ++timesOfAge[age];

     }

    // sort ages by times

    int index = 0;
    for (int i = 0; i <= OLDEST; ++i)

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

         {

             ages[index] = i;

             ++index;

         }
}

void test_case()

{
     InitAges(ages, MAX);

     PrintAges(ages, MAX);

     SortAges(ages, MAX);

     PrintAges(ages, MAX);
}

int _tmain(int argc, _TCHAR *argv[])

{
     test_case();

    return 0;
}
/*

79 61 74 76 64 1 28 31 31 79

1 28 31 31 61 64 74 76 79 79

*/

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

【参考】

http://zhedahht.blog.163.com/blog/static/25411174201131184017844/

http://blog.csdn.net/sunmeng_007/article/details/8047338

【本文链接】

http://www.cnblogs.com/hellogiser/p/sort-ages-with-hashtable.html

时间: 2024-10-19 21:16:31

53. 特殊的O(n)时间排序[sort ages with hashtable]的相关文章

笔试算法题(53):四种基本排序方法的性能特征(Selection,Insertion,Bubble,Shell)

四种基本算法概述: 基本排序:选择,插入,冒泡,希尔.上述算法适用于小规模文件和特殊文件的排序,并不适合大规模随机排序的文件.前三种算法的执行时间与N2成正比,希尔算法的执行时间与N3/2(或更快)成正比: 前三种算法在平均,最坏情况下都是N2,而且都不需要额外的内存:所以尽管他们的运行时间只相差常数倍,但运行方式不同: 对于已经就序的序列而言,插入排序和冒泡排序的运行时间都是O(N),但是选择排序的时间仍旧是O(N^2): 因为Insertion和Bubble都是相邻项间的比较交换,所以不会出

详细解说 STL 排序(Sort)(转)

作者Winter 详细解说 STL 排序(Sort) 0 前言: STL,为什么你必须掌握 1 STL提供的Sort 算法 1.1 所有sort算法介绍 1.2 sort 中的比较函数 1.3 sort 的稳定性 1.4 全排序 1.5 局部排序 1.6 nth_element 指定元素排序 1.7 partition 和stable_partition 2 Sort 和容器 3 选择合适的排序函数 4 小结 5 参考文档 一切复杂的排序操作,都可以通过STL方便实现 ! 0 前言: STL,为

线性时间排序算法

线性时间排序算法列表 线性时间排序 Name Average Worst Memory Stable Description  计数排序 (Counting Sort) n + k n + k n + k Stable Indexes using key values.  基数排序 (Radix Sort) n * k  n * k n + k Stable Examines individual bits of keys.  桶排序 (Bucket Sort) n + k n2 n * k S

算法导论第八章线性时间排序

一.线性时间排序算法历史概览 计数排序首先是由 Harold H. Seward 于1954年提出,而且他还提出将计数排序和基数排序进行结合的思想:基数排序是L.J.Comrie于1929年首次在一篇描述卡片穿孔机文档中提出的一种方法,它是从最低有效位开始,对一个有多位数组成的数进行排序的方法:而桶排序的基本思想则由E.J.Isaac和R.C.Singleton于1956年提出的,之后很多研究人员在这三种算法的基础上针对不同的应用场景又进一步改进,到了今天一个很成熟.很通用的地步. 二.O(nl

07.everything的搜索历史按照搜索时间排序

需求:everything的搜索历史按照搜索时间排序;(现在是按搜索次数排序的) "Sun Jun 23, 2013 8:14 am"的时候作者就说: Sorting search history by last search date in Everything is on my Things to do list. 但是看了更新日志,翻了菜单,并没有找到相关设置; www.voidtools.com ? View topic - When does Everything saves

算法导论 第八章 线性时间排序(python)

比较排序:各元素的次序依赖于它们之间的比较{插入排序O(n**2) 归并排序O(nlgn) 堆排序O(nlgn)快速排序O(n**2)平均O(nlgn)} 本章主要介绍几个线性时间排序:(运算排序非比较排序)计数排序O(k+n)基数排序O() 第一节:用决策树分析比较排序的下界 决策树:倒数第二层满,第一层可能满的二叉树,它用来表示所有元素的比较操作{于此来分析下界},忽略控制,移动操作 1:2 #A[1]和A[2]比 <= 走左边 >走右边 <3,1,2> 最后的结果 下标对应排

C#实现对指定文件夹中文件按修改时间排序

string path = "~/Document/Introduction/团队管理制度/";            DirectoryInfo dirinfo = new DirectoryInfo(Server.MapPath(path));            FileInfo[] Files = dirinfo.GetFiles();            Array.Sort<FileInfo>(Files, new FIleLastTimeComparer(

详细解说 STL 排序(Sort)

http://www.cppblog.com/mzty/archive/2005/12/15/1770.html 详细解说 STL 排序(Sort) 0 前言: STL,为什么你必须掌握 1 STL提供的Sort 算法 1.1 所有sort算法介绍 1.2 sort 中的比较函数 1.3 sort 的稳定性 1.4 全排序 1.5 局部排序 1.6 nth_element 指定元素排序 1.7 partition 和stable_partition 2 Sort 和容器 3 选择合适的排序函数

算法导论——lec 08 线性时间排序

之前我们介绍了几种O(nlgn)的排序算法:快速排序.合并排序和堆排序,本节我们介绍基于比较的排序算法的下界以及几个线性时间的排序算法--计数排序.基数排序.桶排序. 一. 比较排序算法的下界 1. 决策树模型:比较排序可以被抽象的视为决策树.一棵决策树是一棵满二叉树,表示某排序算法 作用于给定输入所做的所有比较. 排序算法的执行对应于遍历一条从树的根到叶结点的路径.在每个内节结点处要做比较. 要使排序算法能正确的工作,其必要条件是,n 个元素的n!种排列中的每一种都要作为决策树 的一个叶子而出