先吐槽一下这个难度,咋也不能是easy啊,和其他easy的不在一个量级。
Given a list of scores of different students, return the average score of each student's top five scores in the order of each student's id.
Each entry items[i]
has items[i][0]
the student's id, and items[i][1]
the student's score. The average score is calculated using integer division.
Example 1:
Input: [[1,91],[1,92],[2,93],[2,97],[1,60],[2,77],[1,65],[1,87],[1,100],[2,100],[2,76]] Output: [[1,87],[2,88]] Explanation: The average of the student with id = 1 is 87. The average of the student with id = 2 is 88.6. But with integer division their average converts to 88.
Note:
1 <= items.length <= 1000
items[i].length == 2
- The IDs of the students is between
1
to1000
- The score of the students is between
1
to100
- For each student, there are at least 5 scores
Approach #1 Brute Force, sorting
这是我的解法,还有一些莫名其妙的test case没有通过。
class Solution {
public int[][] highFive(int[][] items) {
int rows = items.length;
Set<Integer> set = new HashSet();
// first sort all items by grades
for(int i=0; i<rows; i++){
int min = i;
set.add(items[i][0]);
for(int j=i+1; j<rows;j++){
if(items[j][1]<items[min][1]){
min = j;
}
}
if(min!=i){
int[] temp = items[i];
items[i] = items[min];
items[min] = temp;
}
}
// now start construct the answer array
Object[] obj = set.toArray();
int id[] = new int[obj.length];
int[][] ans = new int[obj.length][2];
for (int i = 0; i <obj.length; i++) {
id[i] = (int) obj[i];
ans[i][0] = id[i];
}
// now focus on calculating the average score
for (int i=0; i<obj.length; i++){
int count = 0;
int sum = 0;
int j = rows-1;
while(count<5){
if(items[j][0] == ans[i][0]){
sum += items[j][1];
count += 1;
j-=1;
}
else {j-=1; continue;}
}
ans[i][1] = sum/5;
}
return ans;
}
}
结果:
莫名其妙少了一个学生的成绩。
Wrong Answer
Input
[[1,46],[1,44],[1,92],[1,26],[1,90],[2,7],[2,76],[2,20],[2,46],[2,68],[3,8],[3,55],[3,66],[3,55],[3,62],[4,22],[4,90],[4,92],[4,13],[4,89],[5,13],[5,20],[5,82],[5,83],[5,25],[6,83],[6,89],[6,33],[6,16],[6,70],[7,85],[7,15],[7,33],[7,72],[7,9]]
Output
[[1,59],[2,43],[3,49],[4,61],[5,44],[6,58]]
Expected
[[1,59],[2,43],[3,49],[4,61],[5,44],[6,58],[7,42]]
分析
我的思路是,先把所有的行按照学生成绩这一列来排序,然后用set储存所有学生的id来避免重复,再用set构造最终解的第一列,然后从排好序的成绩列表里,按照id,每次选最高的5个算出均分。
Approach #2 HashMap, PriorityQueue
摸一下大神的解法。
class Solution {
public int[][] highFive(int[][] items) {
HashMap<Integer, PriorityQueue<Integer>> map = new HashMap<>();
for(int[] item : items){
int id = item[0];
int score = item[1];
if(!map.containsKey(id)){
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(5);
pq.offer(score);
map.put(id, pq);
}else{
PriorityQueue<Integer> pq = map.get(id);
pq.offer(score);
if(pq.size() > 5){
pq.poll();
}
map.put(id, pq);
}
}
int index = 0;
int[][] res = new int[map.size()][2];
for(int id : map.keySet()){
res[index][0] = id;
PriorityQueue<Integer> pq = map.get(id);
int sum = 0;
int size = pq.size();
while(!pq.isEmpty()){
sum+= pq.poll();
}
res[index][1] = sum/size;
index++;
}
return res;
}
}
分析
本题使用PriorityQueue是十分自然的:
1>PriorityQueue是一种无界的,线程不安全的队列
2>PriorityQueue是一种通过数组实现的,并拥有优先级的队列
3>PriorityQueue存储的元素要求必须是可比较的对象, 如果不是就必须明确指定比较器
参考下面这篇文章: