Java Homework - 學生分數排序器
Java 班第四份 Java 作業的其中一題,給定 n 個學生在 m 次考試內的所有成績,求每位學生取得單次考試內最高分的次數。原題目有給出 8 個學生考 6 次考試的每個分數 (共 48 個),不過我是寫了個隨機分數產生器 randomAllScores(m, n),方便測試用。
作法
首先,考量方便直接從一次考試的所有分數內找出最高的分數,randomAllScores() 產生的二維陣列 allScores,設計成:
{考試 1:{學生 1 分數, 學生 2 分數, 學生 3 ...}, 考試 2:{ ... }, ... ... }
再來準備了一組外層是學生個數,內層含學生編號和次數紀錄的二維陣列 studentRecords ,用於最後結果輸出。
計算過程,利用迴圈從全部分數按考試取得 highest 這個整數陣列,表示同學裡誰拿最高分。若是某學生的分數最高,則將該學生的元素 + 1 表示,例如 {0, 0, 1, 0, 0, 0, 0, 0} 即代表考最高分的是第三個學生。之後便可將這陣列的所有元素按順序加到 studentRecords 裡每個學生的次數元素,有加到 1 便是最高分次數加一次。所有考試都執行過這組動作即完成計算,最後輸出。
由於取得 highest 的 studentsWithHighestScore() 會檢查所有的學生分數 (迴圈),然後 hasHighestScore() 每檢查一個便會拿該分數跟所有分數比較 (迴圈內再迴圈),顯然這是個沒有特別技巧的暴力解法:計算步驟為 n^2。當學生人數 n 很大時,程式的效率並不好。
用 array、rank、largest element 等關鍵字搜尋可以查到很多相關題型的作法,目前看到最順眼的是 GeeksforGeeks 這篇 k largest (or smallest) elements in an array 裡的 quick sort 作法,之後研究怎麼應用到這一題。
package junli.hw4;
public class StudentScoreRanker {
public static void main(String[] args) {
// Set up data
int[] numOfStudents = 8;
int[][] allScores = randomAllScores(6, numOfStudents);
int[][] studentRecords = prepareRecordArray(numOfStudents);
// System.out.println("All scores: " + Arrays.deepToString(allScores));
// Process
for(int i = 0; i < allScores.length; i++) {
int[] highest = studentsWithHighestScore(allScores[i]);
// System.out.println(Arrays.toString(highest));
addHighestRecord(highest, studentRecords);
}
// Output
System.out.println("學員\t 最高分次數");
for(int i = 0; i < studentRecords.length; i++) {
System.out.printf(" %d:\t\t%d\n", studentRecords[i][0], studentRecords[i][1]);
}
}
private static void addHighestRecord(int[] highest, int[][] studentRecords) {
for(int i = 0; i < highest.length; i++) {
studentRecords[i][1] += highest[i];
}
}
private static int[] studentsWithHighestScore(int[] test) {
int[] array = new int [test.length];
for(int i = 0; i < test.length; i++) {
if(hasHighestScore(test, test[i])) {
array[i] += 1;
}
}
return array;
}
private static boolean hasHighestScore(int[] test, int score) {
for(int i = 0; i < test.length; i++) {
if(test[i] > score) {
return false;
}
}
return true;
}
private static int[][] prepareRecordArray(int numOfStudents) {
int[][] array = new int [numOfStudents][2];
for(int i = 0; i < numOfStudents; i++) {
int[] r = {i + 1, 0};
array[i] = r;
}
return array;
}
private static int[][] randomAllScores(int numOfTests, int numOfStudents) {
int[][] twoDiArray = new int [numOfTests][numOfStudents];
for(int i = 0; i < numOfTests; i++) {
for(int j = 0; j < numOfStudents; j++) {
twoDiArray[i][j] = randomNumInRange(0, 100);
}
}
return twoDiArray;
}
private static int randomNumInRange(int min, int max) {
return (int) (Math.random() * (max - min + 1) + min);
}
}
留言
張貼留言