全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
题目:取出尽量少的球
时间限制:1s 空间限制:32MB 限定语言:不限
题目描述:
某部门开展Family Day开放日活动,其中有个从桶里取球的游戏,游戏规则如下:有N个容量一样的小桶等距排开,且每个小桶都默认装了数量不等的小球,每个小桶所装的小球数量记录在数组bucketBallNums中,游戏开始时,要求所有桶的小球总数不能超过SUM,如果小球总数超过SUM,则需对所有的小桶统一设置一个容量最大值maxCapacity,并需将超过容量最大值的小球拿出来,直至小桶里的小球数量小于maxCapacity;请您根据输入的数据,计算从每个小桶里拿出的小球数量?
限制规则一:
如果所有小桶的小球总和小于SUM,则无需设置容量值,并且无需从小桶中拿球出来,返回结果[];
限制规则二:
如果所有小桶的小球总和大于SUM,则需设置容量最大值maxCapacity,并且需从小桶中拿球出来,返回从每个小桶拿出的小球数量组成的数组;
输入描述:
第一行输入2个正整数,数字之间使用空格隔开,其中第一个数字表示SUM;第二个数字表示bucketBallNums数组长度;
第二行输入N个正整数,数字之间使用空格隔开,表示bucketBallNums的每一项;
输出描述:
从每个小桶里拿出的小球数量,并使用一维数组表示
补充说明:
1 <= bucketBallNums[i] <= 10^9
1 <= bucketBallNums.length = N <= 10^5
1 <= maxCapacity <= 10^9
1 <= SUM <= 10^9
示例1
输入:
14 7
2 3 2 5 5 1 4
输出:
[0,1,0,3,3,0,2]
说明:
小球总数为22,SUM=14,超出范围了,需从小桶取球,maxCapacity=1,取出球后,桶里剩余小球总和为7,远小于14;maxCapacity=2,取出小球后,桶里剩余小球总和为13,小于最大值;maxCapacity=3,取出小球后,桶里剩余小球总和为16,大于14;因此maxCapacity=2,每个小桶小球数量大于2的都需要拿出来;
maxCapacity = 1,取出超出容量的球后,总数=6,远小于SUM=14
maxCapacity = 2,取出超出容量的球后,总数=13,小于SUM =14
maxCapacity = 3,取出超出容量的球后,总数=17,大于SUM =14
示例2
输入:
3 3
1 2 3
输出:
[0,1,2]
说明:
小球总数为6,SUM=3,超出范围了,需从小桶取球,maxCapacity=1,则小球总数为3,从1号桶取0个球,1号桶取1个球,2号桶取2个球;
示例3
输入:
6 2
3 2
输出:
[]
说明:
小球总数为5,SUM=6,在范围内,无需从小桶取球;
解题思路:
先求出maxCapacity的最小值和最大值。
最小值:SUM/bucketBallNums,比如SUM=15,bucketBallNums=7;
则maxCapacity至少需要2层,因为2层只有14个球,而三层至多可能有21个球。
最大值:所有小桶里面球数最多的那个
如例1所示:
对maxCapacity从14/7=2遍历到5;
当maxCapacity=2时,取出多余的球后,剩余球为13,小于14
当maxCapacity=3是,取出多余的球后,剩余球为17,大于14
此时确定maxCapacity=2,且取出的球的数组为[0,1,0,3,3,0,2]
代码实现:
package com.codernav.demo.hwod.exam; import java.util.Scanner; /** * @title 取出尽量少的球 * @Description 某部门开展Family Day开放日活动,其中有个从桶里取球的游戏,游戏规则如下:有N个容量一样的小桶等距排开,且每个小桶都默认装了数量不等的小球,每个小桶所装的小球数量记录在数组bucketBallNums中,游戏开始时,要求所有桶的小球总数不能超过SUM,如果小球总数超过SUM,则需对所有的小桶统一设置一个容量最大值maxCapacity,并需将超过容量最大值的小球拿出来,直至小桶里的小球数量小于maxCapacity;请您根据输入的数据,计算从每个小桶里拿出的小球数量? * 限制规则一: * 如果所有小桶的小球总和小于SUM,则无需设置容量值,并且无需从小桶中拿球出来,返回结果[]; * 限制规则二: * 如果所有小桶的小球总和大于SUM,则需设置容量最大值maxCapacity,并且需从小桶中拿球出来,返回从每个小桶拿出的小球数量组成的数组; * @Author 开发者导航 * @website https://codernav.com * @date 2023/5/14 */ public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); long SUM = sc.nextLong(); int bucketBallNums = sc.nextInt(); //球的总数 long ballCount = 0; //所有桶中球数量的数组 long[] ballNums = new long[bucketBallNums]; //单桶最多球的数量 long max = 0; for (int i = 0; i < bucketBallNums; i++) { ballNums[i] = sc.nextInt(); ballCount += ballNums[i]; max = Math.max(max, ballNums[i]); } if (ballCount <= SUM) { //小桶的小球总和小于SUM,则无需设置容量值,并且无需从小桶中拿球出来,返回结果[] System.out.println("[]"); } else { long l = 0, r = max; while (l < r) { //每个桶所剩球的数量 long mid = (l + r + 1) / 2; //桶中所剩球的总量 long tmp = 0; for (int i = 0; i < bucketBallNums; i++) { tmp += Math.min(mid, ballNums[i]); } if (tmp <= SUM) { l = mid; } else { r = mid - 1; } } StringBuilder ans = new StringBuilder("["); for (int i = 0; i < bucketBallNums; i++) { if (i != 0) ans.append(","); ans.append(Math.max(0, ballNums[i] - l)); } ans.append("]"); System.out.println(ans); } } }