1. 题目与解析
一所学校里有一些班级,每个班级里有一些学生,现在每个班都会进行一场期末考试。给你一个二维数组 classes ,其中 classes[i] = [passi, totali] ,表示你提前知道了第 i 个班级总共有 totali 个学生,其中只有 passi 个学生可以通过考试。
给你一个整数 extraStudents ,表示额外有 extraStudents 个聪明的学生,他们 一定 能通过任何班级的期末考。你需要给这 extraStudents 个学生每人都安排一个班级,使得 所有 班级的 平均 通过率 最大 。
一个班级的 通过率 等于这个班级通过考试的学生人数除以这个班级的总人数。平均通过率 是所有班级的通过率之和除以班级数目。
请你返回在安排这 extraStudents 个学生去对应班级后的 最大 平均通过率。与标准答案误差范围在 10-5 以内的结果都会视为正确结果。
输入: classes = [[1,2],[3,5],[2,2]], extraStudents = 2
输出: 0.78333
解释: 你可以将额外的两个学生都安排到第一个班级,平均通过率为 (3/4 + 3/5 + 2/2) / 3 = 0.78333 。
输入: classes = [[2,4],[3,9],[4,5],[2,10]], extraStudents = 4
输出: 0.53485
我们可以用贪心的思想来解析这道题,所有的 extraStudents 聪明学生,我们肯定都希望每一个人进行安排的时候,都能获得最好的效果,也就是说,每一次放入一个学生,都保证对于整体比例增加的最大就好,即passi+1/totali+1 - passi/totali最大。那么我们就可以用这个标准建立一个大根堆,每一次都给该指标最大的班级+1。
2. 题解
class Solution {
public double maxAverageRatio(int[][] classes, int extraStudents) {
PriorityQueue<double[]> pq = new PriorityQueue<>((a, b) -> {
double x = (a[0] + 1) / (a[1] + 1) - a[0] / a[1];
double y = (b[0] + 1) / (b[1] + 1) - b[0] / b[1];
return Double.compare(y, x);
});
for (var e : classes) {
pq.offer(new double[] {e[0], e[1]});
}
while (extraStudents-- > 0) {
var e = pq.poll();
double a = e[0] + 1, b = e[1] + 1;
pq.offer(new double[] {a, b});
}
double ans = 0;
while (!pq.isEmpty()) {
var e = pq.poll();
ans += e[0] / e[1];
}
return ans / classes.length;
}
}