1. 【经典算法】 得分排行
1.1 算法描述
如果有一教师依学生座号输入考试分数,现希望在输入完成后自己主动显示学生分数的排行。当然学生的分数可能同样。
1.2 算法解析
1.2.1 基础版本
使用额外的一个排行数组来遍历分数数组即可。方法虽然简单,但是反覆计算的次数是n^2
,如果n值变大,那么运算的时间就会拖长。
public static void printScoreRank01(int[] score) {
int count = score.length;
int[] order = new int[count + 2];
for(int i = 0; i < count; i++) {
order[i] = 1;
for(int j = 0; j < count; j++) {
if(score[j] > score[i]) {
order[i]++;
}
}
}
System.out.println("得分\t排行\n");
for(int i = 0; i < count; i++) {
System.out.println(score[i] + "\t" + order[i]);
}
}
1.2.2 递进版本
设定排名数组rank的长度为n+2,并将初始值设定为0,如下所示:
接下来遍历分数阵列,并在分数所对应的排行数组的索引元素上加1,如下所示:
将排名数组最右边的元素设定为1,然后依序将右边的元素值加至左边一个元素,最后排行阵列中的“分数+1””就是得该分数的排行,如下所示:
这种方式看起来复杂,其实就是在计算某个分数之前排行的人数,假设89分之前的排行人数为x人,则89分自然就是x+1了,这也是为什么数组最右边要设定为1的原因;如果89分有y人,则88分自然就是x+y+1,整个数组右边元素向左加的原因正是如此。
public static void printScoreRank02(int[] score) {
int count = score.length;
int[] rank = new int[MAX_SCORE + 2];
for (int i = 0; i < count; i++) {
rank[score[i]]++;
}
rank[MAX_SCORE + 1] = 1;
for (int i = MAX_SCORE; i >= 0; i--) {
rank[i] = rank[i] + rank[i + 1];
}
System.out.println("得分\t排行\n");
for (int i = 0; i < count; i++) {
System.out.println(score[i] + "\t" + rank[score[i] + 1]);
}
}
1.3 代码执行
package com.gavinbj.leetcode.classic;
/**
* 假设有一教师依学生座号输入考试分数,现希望在输入完毕后自动显示学生分数的排行。 注意学生的分数可能相同。
*
* @author gavinbj
*
*/
public class ScoreRanking {
// 以百分之为例,其他的特殊分数在进行调整
public static final int MAX_SCORE = 100;
public static void main(String[] args) {
// 随机创建一批成绩作为输入参数。
int[] arr = new int[30];
for(int i=0; i<30; i++) {
arr[i] = (int)(Math.random()*100);
}
// 分别调用两种排序进行排序
printScoreRank01(arr);
printScoreRank02(arr);
}
/**
* 得分排行01: 使用额外的一个排行数组便利分数数组阵列
* 计算的次数是n^2, 如果n值变大,那么运算的时间就会超长
*
* @param score
*/
public static void printScoreRank01(int[] score) {
int count = score.length;
int[] order = new int[count + 2];
for(int i = 0; i < count; i++) {
order[i] = 1;
for(int j = 0; j < count; j++) {
if(score[j] > score[i]) {
order[i]++;
}
}
}
System.out.println("得分\t排行\n");
for(int i = 0; i < count; i++) {
System.out.println(score[i] + "\t" + order[i]);
}
}
/**
* 得分排行02:
* 1.遍历分数数组score,获得各分数人数的数组rank
* 2.对rank分数数组进行向左相加处理,获得终于分数相应的排名
*
* @param score
*/
public static void printScoreRank02(int[] score) {
int count = score.length;
int[] rank = new int[MAX_SCORE + 2];
for (int i = 0; i < count; i++) {
rank[score[i]]++;
}
rank[MAX_SCORE + 1] = 1;
for (int i = MAX_SCORE; i >= 0; i--) {
rank[i] = rank[i] + rank[i + 1];
}
System.out.println("得分\t排行\n");
for (int i = 0; i < count; i++) {
System.out.println(score[i] + "\t" + rank[score[i] + 1]);
}
}
}
执行结果:
得分 排行
87 10
94 4
69 14
88 9
97 3
75 12
93 6
21 26
45 18
50 16
98 1
98 1
24 24
0 30
42 20
45 18
75 12
76 11
26 23
51 15
91 7
1 28
1 28
22 25
31 21
46 17
29 22
94 4
4 27
89 8