LeetCode 1792. 最大平均通过率

文章讨论了如何通过优先队列和自定义大根堆实现最大平均通过率的问题。提供的Java代码示例展示了如何处理班级的通过率,以及在给定额外学生名额的情况下,如何优化分配以最大化总体平均通过率。算法的核心是选择能最大化比率的班级优先分配学生。
摘要由CSDN通过智能技术生成

1792. 最大平均通过率

 

 

 【优先队列】为了使得最后的平均通过率最大,我们应该让(pass + 1) / (total + 1) - pass / total大的先用掉extra,所以对于两个班级可以按照这个进行排序,接下来发现extra只有1e5,classes也是1e5,如果用优先队列来存classes的话,操作1e5次也不会超时。

class Solution {
    public double maxAverageRatio(int[][] classes, int extraStudents) {
        int n = classes.length;
        PriorityQueue<double[]> queue = new PriorityQueue<double[]>((a, b) -> {
            return (a[0] + 1) / (a[1] + 1) - a[0] / a[1] > (b[0] + 1) / (b[1] + 1) - b[0] / b[1]? -1: 1;
        });
        for (int[] c: classes) {
            queue.offer(new double[] {c[0], c[1]});
        }
        int ex = extraStudents;
        double sum = 0;
        while (ex-- > 0) {
            double[] t = queue.peek();
            queue.poll();
            queue.offer(new double[] {t[0] + 1, t[1] + 1});
        }
        for (double[] c: queue) {
            sum += c[0] / c[1];
        }
        return sum / n;
    }
}

【手写堆】试一下用Java写个大根堆

class Solution {

    int n;
    double[][] heap;

    boolean cmp(int i, int j) {
        double[] a = heap[i], b = heap[j];
        return (a[0] + 1) / (a[1] + 1) - a[0] / a[1] > (b[0] + 1) / (b[1] + 1) - b[0] / b[1] ? true: false;
    }

    void swap(int i, int j) {
        double a = heap[i][0], b = heap[i][1];
        heap[i][0] = heap[j][0]; heap[i][1] = heap[j][1];
        heap[j][0] = a; heap[j][1] = b;
    }

    void down(int i) {
        int l = i * 2, r = i * 2 + 1, t = i;
        if (l <= n && cmp(l, t)) t = l;
        if (r <= n && cmp(r, t)) t = r;
        if (t != i) {
            swap(t, i);
            down(t);
        }
    }

    public double maxAverageRatio(int[][] classes, int extraStudents) {
        n = classes.length;
        heap = new double[n + 1][2];
        int ex = extraStudents;
        for (int i = 0; i < n; i++) {
            heap[i + 1][0] = classes[i][0];
            heap[i + 1][1] = classes[i][1];
        }
        for (int i = n / 2; i >= 1; i--) down(i);
        while (ex-- > 0) {
            heap[1][0]++;
            heap[1][1]++;
            down(1);
        }
        double sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += heap[i][0] / heap[i][1];
        }
        return sum / n;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值