华为OD机试 新系统 题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
给定一个停车场某一天的车辆出入记录,请计算该停车场的当日收入,收费规则如下:
• 停车半小时收费1元,不足半小时按半小时计算。
• 一辆车每天收费封顶15元。
• 停车时间小于半小时则不收费
• 11:30 - 13:30 不计入停车时间。
• 包月的车辆不统计当日收入。
二、输入描述
第一段是购买了包月服务的车辆信息:第一行是包月车辆的数量,从第二行开始,每行是一个包月的车牌号。
第二段是当日车辆出入记录:格式为:时(24小时制):分 车牌号(6~10位) enter/leave
三、输出描述
停车场当日收入,整数。
备注
假设所有车辆在当天进当天离。每天的车辆出入记录<10000条,包月车辆个数小于10000。
四、测试用例
测试用例1:
1、输入
1
A12345
01:28 A12345 enter
01:59 A12345 leave
2、输出
0
3、说明
该车是包月车,不计入收入。
测试用例2:
1、输入
0
08:00 A12346 enter
11:20 A12345 enter
11:30 A12346 leave
12:00 A12345 leave
2、输出
7
3、说明
A12346:08:00~11:30,共 210 分钟,收费 210/30=7 元。
A12345:11:20~12:00,共 40 分钟,但 11:30~12:00 这 30 分钟免费,所以有效时长只有 10 分钟,小于 30 分钟,不收费。
总收入 = 7。
五、解题思路
- 读取包月车列表,存入 HashSet。
- 按行读取当天的出入记录,直到输入结束。
- 遇到 enter:记录该车的入场时间。
- 遇到 leave:找到对应的入场时间;
- 若是包月车,直接忽略;
- 否则计算本次停车费用;
- 将费用累加到该车当天总费用中,最多 15 元。
- 最后把所有非包月车辆的费用求和输出。
六、Java算法源码
publicclassOdTest{// 免费时段开始:11:30privatestaticfinalintFREE_START=11*60+30;// 免费时段结束:13:30privatestaticfinalintFREE_END=13*60+30;// 每辆车每天收费封顶privatestaticfinalintCAP=15;/** * 将 "HH:mm" 格式的时间转成分钟数 * 例如: * 01:28 -> 88 * 13:30 -> 810 */privatestaticintparseTime(StringtimeStr){String[]parts=timeStr.split(":");inthour=Integer.parseInt(parts[0]);intminute=Integer.parseInt(parts[1]);returnhour*60+minute;}/** * 计算一段停车记录的有效停车分钟数 * 规则:11:30 - 13:30 不计入停车时间 * * 计算方法: * 1、先算总时长 leave - enter * 2、再算这段停车时间和免费时段的重叠时长 * 3、有效时长 = 总时长 - 重叠时长 */privatestaticintgetEffectiveMinutes(intenterTime,intleaveTime){inttotal=leaveTime-enterTime;// 求两段区间 [enterTime, leaveTime) 和 [FREE_START, FREE_END) 的重叠长度intoverlap=Math.max(0,Math.min(leaveTime,FREE_END)-Math.max(enterTime,FREE_START));returntotal-overlap;}/** * 根据有效停车分钟数计算本次收费 * 规则: * 1、小于30分钟,不收费 * 2、达到30分钟及以上,每30分钟收费1元,不足30分钟按30分钟算 */privatestaticintcalcFee(intminutes){if(minutes<30){return0;}// 向上取整:ceil(minutes / 30.0)return(minutes+29)/30;}publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);// 如果没有输入,直接结束if(!sc.hasNextInt()){return;}// 第一行:包月车辆数量intn=Integer.parseInt(sc.nextLine().trim());// 存包月车牌Set<String>monthlyCars=newHashSet<>();// 读取包月车辆车牌for(inti=0;i<n;i++){monthlyCars.add(sc.nextLine().trim());}// 记录某辆车最近一次 enter 的入场时间Map<String,Integer>enterMap=newHashMap<>();// 记录某辆车当天累计费用Map<String,Integer>feeMap=newHashMap<>();// 读取后续所有出入记录,直到 EOFwhile(sc.hasNextLine()){Stringline=sc.nextLine().trim();// 跳过空行if(line.isEmpty()){break;}String[]arr=line.split("\\s+");StringtimeStr=arr[0];Stringplate=arr[1];Stringaction=arr[2];// 包月车不计入收入,直接忽略其出入记录if(monthlyCars.contains(plate)){continue;}intcurrentTime=parseTime(timeStr);if("enter".equals(action)){// 记录入场时间enterMap.put(plate,currentTime);}elseif("leave".equals(action)){// 找到对应入场时间IntegerenterTime=enterMap.remove(plate);// 理论上题目保证当天进当天离,这里做健壮性保护if(enterTime==null){continue;}// 计算本次有效停车时间inteffectiveMinutes=getEffectiveMinutes(enterTime,currentTime);// 计算本次费用intfee=calcFee(effectiveMinutes);// 累加到该车当天总费用,并做15元封顶inttotalFee=feeMap.getOrDefault(plate,0)+fee;feeMap.put(plate,Math.min(CAP,totalFee));}}// 汇总所有非包月车辆当天收费inttotalIncome=0;for(intfee:feeMap.values()){totalIncome+=fee;}// 按要求输出整数,不要输出额外提示文字System.out.print(totalIncome);}}七、效果展示
1、输入
0
09:00 C11111 enter
12:00 C11111 leave
14:00 C11111 enter
16:00 C11111 leave
2、输出
9
3、说明
同一辆车两次停车:
第一次:09:00~12:00,共 180 分钟
免费时段重叠 11:30~12:00,共 30 分钟
有效时长 150 分钟
收费 150/30=5 元
第二次:14:00~16:00,共 120 分钟
不与免费时段重叠
收费 120/30=4 元
总计 9 元。
🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 新系统 200分)
🏆本专栏收录于《华为OD机试(JAVA)真题》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。