[LeetCode] 1760. Minimum Limit of Balls in a Bag
You are given an integer array nums where the ith bag contains nums[i] balls. You are also given an integer maxOperations.
You can perform the following operation at most maxOperations times:
Take any bag of balls and divide it into two new bags with a positive number of balls.
For example, a bag of 5 balls can become two new bags of 1 and 4 balls, or two new bags of 2 and 3 balls.
Your penalty is the maximum number of balls in a bag. You want to minimize your penalty after the operations.
Return the minimum possible penalty after performing the operations.
Example 1:
Input: nums = [9], maxOperations = 2
Output: 3
Explanation:
- Divide the bag with 9 balls into two bags of sizes 6 and 3. [9] -> [6,3].
- Divide the bag with 6 balls into two bags of sizes 3 and 3. [6,3] -> [3,3,3].
The bag with the most number of balls has 3 balls, so your penalty is 3 and you should return 3.
Example 2:
Input: nums = [2,4,8,2], maxOperations = 4
Output: 2
Explanation:
- Divide the bag with 8 balls into two bags of sizes 4 and 4. [2,4,8,2] -> [2,4,4,4,2].
- Divide the bag with 4 balls into two bags of sizes 2 and 2. [2,4,4,4,2] -> [2,2,2,4,4,2].
- Divide the bag with 4 balls into two bags of sizes 2 and 2. [2,2,2,4,4,2] -> [2,2,2,2,2,4,2].
- Divide the bag with 4 balls into two bags of sizes 2 and 2. [2,2,2,2,2,4,2] -> [2,2,2,2,2,2,2,2].
The bag with the most number of balls has 2 balls, so your penalty is 2, and you should return 2.
Constraints:
1 <= nums.length <= 105
1 <= maxOperations, nums[i] <= 109
袋子里最少数目的球。
给你一个整数数组 nums ,其中 nums[i] 表示第 i 个袋子里球的数目。同时给你一个整数 maxOperations 。你可以进行如下操作至多 maxOperations 次:
选择任意一个袋子,并将袋子里的球分到 2 个新的袋子中,每个袋子里都有 正整数 个球。
比方说,一个袋子里有 5 个球,你可以把它们分到两个新袋子里,分别有 1 个和 4 个球,或者分别有 2 个和 3 个球。
你的开销是单个袋子里球数目的 最大值 ,你想要 最小化 开销。请你返回进行上述操作后的最小开销。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-limit-of-balls-in-a-bag
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
思路是二分,而且是在答案上二分。因为题目给定了最多的操作次数,记为 maxOperations,所以我们的二分是在答案上二分 - 意思是用二分在 1 - Integer.MAX_VALUE 这个区间内尝试一个值,然后看看以这个值作为开销 penalty,所对应的操作次数是多少,如果这个操作次数超过了 maxOperations,就需要移动 left 指针,说明为了满足当前这个开销,操作次数超过上限了;反之移动 right 指针,说明开销可以试着更小一点。
这种题看似只能暴力解但是看数据范围一定过不去的,大概率要尝试二分,但是难点在于二分什么东西。
复杂度
时间O(nlogn)
空间O(1)
代码
Java实现
class Solution {
public int minimumSize(int[] nums, int maxOperations) {
int left = 1;
int right = Integer.MAX_VALUE;
while (left < right) {
int mid = left + (right - left) / 2;
int count = helper(mid, nums);
if (count > maxOperations) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
private int helper(int op, int[] nums) {
int count = 0;
for (int num : nums) {
count += (num - 1) / op;
}
return count;
}
}