LeetCode:1760. 袋子里最少数目的球

解题思路:

看了很久也不知道该怎么下手,果断转去题解看答案,所实话官方的题解说的有些抽象,先买那是我自己看了别人的博客和思考后的一些思路:

1、为什么可以用二分查找?

        题目要求你的开销是单个袋子里球数目的 最大值 ,你想要 最小化 开销。也就是获取这个最小值即可,可以很明显的知道这个值位于1~nums[i]的最大值之间,所以完全可以使用二分查找来寻找这个值,假设这个值是mid,如果符合条件的话,则继续寻找[1~mid]并不断更新,如果mid不满足条件的话则去区间[mid+1~max_element]之间寻找。

2、如何判断mid是否满足条件?

       最多操作m次,假设当前二分查找到了mid,那么如果正向思考,我们去分割 m 次,最小开销是否小于等于 mid, 这样思考会比较难想,那么我们尝试去反过来思考,我们直接将每个袋子都分成<=mid,最后判断操作次数是否 <=m即可。 这里的思路借鉴了该篇博客

        那么操作次数如何获取,即只要遍历nums数组,对于每个nums[i]需要[\frac{nums[i]-1}{mid}]次(其中⌊x⌋ 示将x进行下取整)。解释是官方题解上的,这里照搬过来:

  • 当nums[i]<=mid时,我们无需进行操作;
  • 当mid<nums[i]<=2mid时,我们需要进行 11 次操作;
  • 当2mid<nums[i]<=3mid时,我们需要进行 22 次操作;
  • ……

ok剩下就是代码的事了,相信你看到这里官方的题解以及一些个人的题解都能看得明白了。

class Solution:
    def minimumSize(self, nums: List[int], maxOperations: int) -> int:
        left, right, ans = 1, max(nums), 0
        while left <= right:
            mid = (left + right) // 2
            # 这里ops即为算出来的需要的操作次数,来判断该mid是否可行
            ops = sum((x - 1) // mid for x in nums)
            if ops <= maxOperations:
                ans = mid
                right = mid - 1
            else:
                left = mid + 1
        
        return ans

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值