当前位置: 首页 > news >正文

`[特殊字符]LeetCode每日一题 1792. 最大平均通过率(打卡第一天)`

🐋LeetCode每日一题 1792. 最大平均通过率(打卡第一天)

一所学校里有一些班级,每个班级里有一些学生,现在每个班都会进行一场期末考试。给你一个二维数组 classes ,其中 classes[i] = [passi, totali] ,表示你提前知道了第 i 个班级总共有 totali 个学生,其中只有 passi 个学生可以通过考试。

给你一个整数 extraStudents ,表示额外有 extraStudents 个聪明的学生,他们 一定 能通过任何班级的期末考。你需要给这 extraStudents 个学生每人都安排一个班级,使得 所有 班级的 平均 通过率 最大 。

一个班级的 通过率 等于这个班级通过考试的学生人数除以这个班级的总人数。平均通过率 是所有班级的通过率之和除以班级数目。

请你返回在安排这 extraStudents 个学生去对应班级后的 最大 平均通过率。与标准答案误差范围在 10-5 以内的结果都会视为正确结果。

示例 1:
输入:classes = [[1,2],[3,5],[2,2]], extraStudents = 2
输出:0.78333
解释:你可以将额外的两个学生都安排到第一个班级,平均通过率为 (3/4 + 3/5 + 2/2) / 3 = 0.78333 。

示例 2:
输入:classes = [[2,4],[3,9],[4,5],[2,10]], extraStudents = 4
输出:0.53485

提示:
1 <= classes.length <= 105
classes[i].length == 2
1 <= passi <= totali <= 105
1 <= extraStudents <= 105

题解:

在确定天才学生的放置时,应该优先选择提升潜力更大的位置进行放置,这样才可保证全局最优,而不是仅仅由放置后的班级通过率决定,代码中法一即出现此误区,认为局部最优为全局最优。

代码:

// 误区1: 误以为局部最优即为全局最优 即应该选择提升潜力更大 而不是仅仅值大
// 误区2: (double)(classes[i][0] / classes[i][1]) 这样会导致先进行整型运算再转换为double 会损失精度
//        即应该先转为double再进行除法运算
// 误区3: 应利用优先队列实现堆 而非每次进行重新排序
class Solution {public double maxAverageRatio(int[][] classes, int extraStudents) {// 通过率达1的必然不会加人 或理解为加不加对通过率没有影响 依然为1// 利用堆排序思想 先对classes预处理 对其每一个都进行分母分子+1模拟 // 第一次故选择建好大根堆中堆顶元素// 之后仅对选中元素进行更新 更新后继续放入堆中 重复上述选择堆顶操作int al_ok = 0;for(int i=0;i<classes.length;i++){if(classes[i][0] == classes[i][1]){al_ok++;}}Exm[] exm = new Exm[classes.length-al_ok];// 100%的记得剔除int index = 0;for(int i=0;i<classes.length;i++){if(classes[i][0] == classes[i][1])continue;Exm e = new Exm();e.id = i;e.val = (double)classes[i][0] / classes[i][1];e.ok = classes[i][0];e.count = classes[i][1];e.later_val = (double)(classes[i][0] + 1) / (classes[i][1] + 1);exm[index++] = e;}Arrays.sort(exm, (o1, o2) -> Double.compare(o2.later_val, o1.later_val));for(int i=0;i<extraStudents;i++){exm[0].val = exm[0].later_val;exm[0].ok++;exm[0].count++;exm[0].later_val = (double)(exm[0].ok + 1) / (exm[0].count + 1);Arrays.sort(exm, (o1, o2) -> Double.compare(o2.later_val, o1.later_val));}double res = al_ok;for(int i=0;i<classes.length-al_ok;i++){res += exm[i].val;}return (double) res / classes.length;}
}
class Exm{int id; // 班级编号int ok; // 此时可通过的人数int count; // 此时总人数double val; // 此时通过率double later_val; // +1处理后通过率
}// 修改后
// 即无需单独建类 使用纯double数组即可实现 因题目仅仅需要进行数值计算
class Solution {public double maxAverageRatio(int[][] classes, int extraStudents) {// 基于提升潜力进行排序 此时即可不用特别筛选出100%PriorityQueue<Double[]> heap = new PriorityQueue<>((o1,o2) -> {double p1 = ((o1[0] + 1) / (o1[1] + 1)) - (o1[0] / o1[1]);double p2 = ((o2[0] + 1) / (o2[1] + 1)) - (o2[0] / o2[1]);return Double.compare(p2,p1);});int len = classes.length;for(int i=0;i<len;i++){Double[] tmp = new Double[2];tmp[0] = classes[i][0] + 0.0;tmp[1] = classes[i][1] + 0.0;heap.offer(tmp);}for(int i=0;i<extraStudents;i++){Double[] tmp = heap.poll();tmp[0]++;tmp[1]++;heap.offer(tmp);}double res = 0;while(!heap.isEmpty()){Double[] tmp = heap.poll();double r1 = tmp[0];double r2 = tmp[1];res += (r1/r2);}return res / len;}
}

结果:

在这里插入图片描述

题外话:

这里看到了一个很唯美的题解,粘贴在这里供大家瞻仰!

在这里插入图片描述

http://www.dtcms.com/a/362108.html

相关文章:

  • 在 React Native 层禁止 iOS 左滑返回(手势返回/手势退出)
  • Unity 串口通讯2 硬件SDK 开发[数据监听,按键监听]
  • 人工智能——课程考核
  • Python OpenCV图像处理与深度学习:Python OpenCV图像几何变换入门
  • 线程池发生了异常该怎么处理?
  • Groovy 的核心语法
  • 计算机视觉与深度学习 | 传统图像处理技术的未来发展前景分析
  • 算法练习——169.多数元素
  • 焦耳热技术助力顶刊研究:薄层质子交换膜实现高效水电解制氢
  • 深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)第八章知识点问答(18题)
  • 在工业质检中,机器视觉与人工检测的决策依据
  • Java类加载机制
  • 亚马逊云代理商:如何选择适合的AWS EC2实例类型?
  • ARM-SPI屏幕案例
  • 1. 叙述与命题
  • 【开题答辩全过程】以 基于JSP的养生网站设计与实现为例,包含答辩的问题和答案
  • 在JAVA中Mybatis的使用
  • GitHub每日最火火火项目(9.1)
  • TDengine 日期时间函数 DAYOFWEEK 使用手册
  • shell编程基础入门-3
  • 人工势场法(APF)路径规划 MATLAB
  • 战略进阶——解读92页培训_战略+概述与基本框架麦肯锡【附全文阅读】
  • 一个好的智能体框架应该是什么样子
  • Transformer的并行计算与长序列处理瓶颈总结
  • Solid Explorer文件管理器:功能强大的安卓文件管理器及网盘文件管理器
  • 2025年职场人士专业证书选择与分析
  • 从 “对话” 到 “共创”:生成式 AI 如何重塑内容创作全流程,普通人也能掌握的高效工具指南
  • Windows 安装配置解压版MongoDb
  • ‌ C++ 继承与派生类
  • 从DevOps到BizDevOps:哪些DevOps工具能够成为业务创新加速引擎?