【经典算法】N001:得分排行

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

发布了37 篇原创文章 · 获赞 24 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/gavinbj/article/details/104161983