1760. 袋子里最少数目的球
思路:
你的开销是单个袋子里球数目的 最大值 ,你想要 最小化 开销。
题目出现:最大值最小,最小值最大 则是二分题
已知开销值y越大,操作数越小,则问题具有单调性,可以用二分
二分查找每个开销值y,找到y最小的且不超过操作次数的那一个
- 从答案开始搜索 设y为开销值
- 我们需要在满足 操作数≤operation 的情况下 让y尽量小
- 计算每个袋子分到最大值为y个球所需的操作数总和sum
- 如果sum<=operation 则缩右边界 让y变小
- 如果sum>operation 则说明y值小了 增大y值
- 最后搜索到的y值就是满足 操作数≤operation 且尽量小的球数
每个袋子操作数怎么计算?
设第i个袋子的球数为x 此时枚举的开销值为y
- 当x≤y时,op=0
- 当y<x≤2y时,op=1 当该袋子有2y个球 只要1次操作就可以分成y y
- 当2y<x≤3y时,op=2
- ……
因此该袋子的操作数为
class Solution {
public:
int minimumSize(vector<int>& nums, int maxOperations) {
int l=1,r=*max_element(nums.begin(),nums.end());
while(l<r)
{
int mid=l+r>>1;
long s=0;
for(int x:nums) s+=(x-1)/mid;
if(s<=maxOperations) r=mid;
else l=mid+1;
}
return l;
}
};
class Solution {
public int minimumSize(int[] nums, int maxOperations) {
int l=1,r=Arrays.stream(nums).max().getAsInt();
while(l<r)
{
int mid=l+r>>1;
long s=0;
for(int x:nums) s+=(x-1)/mid;
if(s<=maxOperations) r=mid;
else l=mid+1;
}
return l;
}
}