leetcode.1760 袋子里最少数目的球 - 反向二分(二分答案)

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
  • ……

因此该袋子的操作数为 \frac{x-1}{y}

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;
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值