在競賽排名、成績統計等場景中,常需將分數數組轉換為對應的名次數組。本文介紹一種簡潔的實現方式:通過排序去重獲取唯一分值,再根據分值在排序陣列中的索引確定名次,自然處理並列名次情況。
輸入:分數陣列 score = {4, 2, 5, 4}
輸出:名次陣列 rank = {2, 3, 1, 2}
規則:分數越高名次越前(數字越小);相同分數並列同一名次,下一名次順延(如兩個第 2 名,下一個是第 4 名)。
List 並去重package test01;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ScoreRank {
// 列印陣列輔助方法
public static void show(int[] arr) {
for (int x : arr) System.out.print(x + " ");
System.out.println();
}
/**
* 根據分數陣列計算名次陣列
* @param score 分數陣列
* @return 名次陣列(相同分數並列同一名次)
*/
public static int[] scoreRank(int[] score) {
// 1. 去重收集唯一分值
List<Integer> uniqueScores = new ArrayList<>();
for (int s : score) {
if (!uniqueScores.contains(s)) {
uniqueScores.add(s);
}
}
// 2. 升序排序後反轉 = 降序
Collections.sort(uniqueScores);
Collections.reverse(uniqueScores);
// 現在 uniqueScores 如 [5, 4, 2] 對應第 1、2、3 名
// 3. 映射原分數到名次
int[] rank = new int[score.length];
for (int i = 0; i < score.length; i++) {
// indexOf 返回首次出現位置,+1 即為名次
rank[i] = uniqueScores.indexOf(score[i]) + 1;
}
return rank;
}
public static void main(String[] args) {
int[] score = {4, 2, 5, 4};
int[] rank = scoreRank(score);
System.out.print("原始分數:");
show(score); // 4 2 5 4
System.out.print("對應名次:");
show(rank); // 2 3 1 2
}
}
原始分數:4 2 5 4
對應名次:2 3 1 2
| 指標 | 複雜度 | 說明 |
|---|---|---|
| 時間複雜度 | O(n²) | List.contains 和 indexOf 皆為 O(n),n 為元素個數 |
| 空間複雜度 | O(n) | 額外儲存唯一分值 List |
| 規則名稱 | 並列處理 | 示例 (分數: 100, 90, 90, 80) |
|---|---|---|
| 標準競爭排名 (1224) | 並列佔位,下一名順延 | 1, 2, 2, 4 |
| 修正競爭排名 (1334) | 並列取平均或最小 | 1, 2.5, 2.5, 4 |
| 密集排名 (1223) | 並列不佔位,下一名緊接 | 1, 2, 2, 3 |
| 序數排名 (1234) | 無並列,按原序區分 | 1, 2, 3, 4 |
本文實現的是標準競爭排名 (1224),最符合一般直覺。
分數轉名次是常見業務邏輯,關鍵在於「去重排序 + 索引映射」。小數據量用 List 簡潔明瞭;大數據量建議用 TreeSet + HashMap 優化查找效能。理解不同排名規則差異,才能根據業務選擇正確算法。