O(n) 时间的算法进行分数排名
来源:互联网 发布:阿里云域名无需备案 编辑:程序博客网 时间:2024/06/05 03:54
一 问题描述
遇到一个常见的分数排名问题,原题的要求是:
已知一个分数数组,数组里面是取值在0-100之间的分数,记为scoreArray。要求输出对应的排名数组scoreRankArray。
比如:scoreArray为[96,95,92,91,97,100,90,88,89,96];
对应应该输出positionArray为:[3,5,6,7,2,1,8,10,9,3]
同样分数的排名相同,但是后续的分数排名将累加。
二 解决方案
解决方案1:
使用比较法,判断数组中比自己分数大的分数的个数,若没有比自己高的分数,排名即为1。所以初始化个数为1。
算法时间复杂度: O(n^2)
算法空间复杂度:O(1)
对应下述的函数:
void getScoreRank(int *scoreArray,int len)
解决方案2:
1. 首先得到每个分数的人数,因为分数在0-100之间, 因此可以声明一个长度为101的数组scoreLibraryArray,数组每个元素的值表示对应下标的分数的个数。比如scoreLibraryArray[90]表示分数为90的人数。
2. 得到每个分数所在的排名,放在数组scoreFullArray中,scoreFullArray[90]表示表示分数为90的排名
3.遍历分数数组scoreArray,根据分数值和scoreFullArray数组中对应分数的排名,得到对应排名数组相应位的排名值。
算法时间复杂度:O(n)
算法空间复杂度:O(1)
对应下述的函数:
void getScoreRank_better(int *scoreArray,int len);
三 代码实现
使用C语言实现并测试一个数组的排名情况:
#include <stdio.h>#include <stdlib.h>void getScoreRank(int *scoreArray,int len);void getScoreRank_better(int *scoreArray,int len);int main () { int scores[10] = {96,95,92,91,97,100,90,88,89,96}; int *scoreArray = scores; static int arraySize = 10; getScoreRank(scoreArray,arraySize); getScoreRank_better(scoreArray,arraySize); return 0;}void getScoreRank(int *scoreArray,int len) { int arraySize = len; int *scoreRankArray = (int *)malloc(sizeof(int)*arraySize); for (int i = 0;i < arraySize;i++) { int scoreRank = 1; for (int j = 0;j < arraySize;j++) { if (*(scoreArray+j) > *(scoreArray+i)) { scoreRank++; } } *(scoreRankArray+i) = scoreRank; } printf("score rank array is:\n["); for (int i = 0;i < arraySize - 1;i++) { printf("%d,",*(scoreRankArray+i)); } printf("%d]\n",*(scoreRankArray + arraySize - 1)); free(scoreRankArray); scoreRankArray = NULL;}void getScoreRank_better(int *scoreArray,int len) { int arraySize = len; int *scoreRankArray = (int *)malloc(sizeof(int)*arraySize); static int scoreRange = 100; int *scoreLibraryArray = (int *)malloc(sizeof(int) * (scoreRange + 1)); for (int i = 0;i < arraySize;i++) { *(scoreRankArray + i) = 0; } for (int i = 0;i <= scoreRange;i++) { *(scoreLibraryArray + i) = 0; } for (int i = 0;i < arraySize;i++) { int scoreI = *(scoreArray + i); *(scoreLibraryArray + scoreI) = *(scoreLibraryArray + scoreI) + 1; } int *scoreFullArray = (int *)malloc(sizeof(int) * (scoreRange+1)); for (int i = 0;i <= scoreRange;i++) { *(scoreFullArray + i) = 0; } int rank = 1; for (int i = 99;i >= 0;i--) { rank += *(scoreLibraryArray + i + 1); *(scoreFullArray + i) = rank; } *(scoreFullArray + scoreRange) = 1; for (int j = 0;j < arraySize;j++) { int score = *(scoreArray + j); int scoreRank = *(scoreFullArray + score); *(scoreRankArray + j) = scoreRank; } printf("better solution: score rank array is:\n["); for (int i = 0;i < arraySize - 1;i++) { printf("%d,",*(scoreRankArray + i)); } printf("%d]\n",*(scoreRankArray + arraySize - 1)); free(scoreRankArray); scoreRankArray = NULL;}
四 运行结果
gcc编译后输出结果如下图:
五 总结
针对大量的数据排名,比如高考分数省级排名(百万级别数据),使用优化后的算法的时间效率提升明显。所以针对分数数据的排名,结合分数是有一定取值范围,无须排序即可完成。与O(n) 时间的算法进行员工年龄排序有异曲同工之妙。该题描述和分析如下:
> 题目:某公司有几万名员工,请完成一个时间复杂度为O(n)的算法对该公司员工的年龄作排序,可使用O(1)的辅助空间。> > 分析:排序是面试时经常被提及的一类题目,我们也熟悉其中很多种算法,诸如插入排序、归并排序、冒泡排序,快速排序等等。这些排序的算法,要么是O(n2)的,要么是O(nlogn)的。可是这道题竟然要求是O(n)的,这里面到底有什么玄机呢?> 题目特别强调是对一个公司的员工的年龄作排序。员工的数目虽然有几万人,但这几万员工的年龄却只有几十种可能。上班早的人一般也要等到将近二十岁才上班,一般人再晚到了六七十岁也不得不退休。
六 注意事项
动态内存分配需要调用free()释放内存并重置为NULL,防止内存泄漏。
free(scoreRankArray); scoreRankArray = NULL;
- O(n) 时间的算法进行分数排名
- 算法时间复杂度的表示法O(n²)、O(n)、O(1)、O(nlogn)
- 时间复杂度为O(n)的排序算法--计数算法
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 一道看上去很吓人的算法面试题:如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
- 注册
- html和JavaScript(一)
- JS 实现万花筒特效 JS 原生代码
- 2017.3.22
- Leetcode刷题(8)-tag(Array)
- O(n) 时间的算法进行分数排名
- quartz教程-基础篇
- sea.js的初次尝试
- 移位运算
- css
- 剑指Offer 14 *调整数组顺序使奇数位于偶数前面
- Java并发编程的艺术-Java中的锁
- iOS透明导航栏的平滑过渡(进阶版)
- 光流法简单介绍