[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;
	}
}
posted @ 2022-12-20 12:59  CNoodle  阅读(138)  评论(0编辑  收藏  举报