第四章:如何运用二分查找算法

labuladong 如何运用二分查找算法

875. 爱吃香蕉的珂珂

  • canFinish() 函数:当前速度下,能吃完的小时数(注意要向上整除
  • 最小速度为1,最大速度为数组中最大值。因此利用二分查找框架求h(h相当于二分查找中的目标值),注意当计算的时间与要求的时间相等时,也是更新右边界。最后返回左边界
  • 关于向上整除(pilespeed都是int型)
    • python
      • python3:pile/speed 是传统除法,除不完时有小数。因此向上整除可以写为math.ceil(pile / speed)
      • python2.6及以前:pile/speed 是向下整除,除不完时无小数(如:17/6=2)。因此向上整除不能写为math.ceil(pile / speed)。要根据是否有余数,将h += math.ceil(pile / speed)改为h += (pile/ speed)+ (1 if pile % speed>0 else 0)
      • python2/python3统一:
        • int(a/b)a//b都表示向下整除。所以可以根据是否有余数,将向上整除统一写为h += int(pile/ speed)+ (1 if pile % speed>0 else 0)h += pile// speed+ (1 if pile % speed>0 else 0)
        • 只要pilespeed中,任意一个为浮点型/就表示传统除法。因此可以通过speed+0.0或者float(speed),将向上整除写为h += math.ceil(pile / (speed+0.0)) 或者h += math.ceil(pile / float(speed))
    • C++:默认的/表示向下除法。可以通过speed+0.0或者float(speed)将int型的speed转成float,再用/进行传统除法,最后用ceil()将其向上转换
    • 如果不想用ceil函数,则两个数相除向上取整可以写为(a + b - 1) / b
class Solution(object):
    def minEatingSpeed(self, piles, H):
        """
        :type piles: List[int]
        :type H: int
        :rtype: int
        """
        import math
        # 当前速度下需要的时间
        def canFinish(piles, speed):
            h = 0
            for pile in piles:
                h += math.ceil(pile / (speed+0.0)) # 或者 h += math.ceil(pile / float(speed))
            return h

        # 二分查找
        l = 1
        r = max(piles)
        while l <= r:
            speed = l + (r - l) // 2
            if canFinish(piles, speed) > H:  # 速度太慢
                l = speed + 1
            elif canFinish(piles,speed) <= H:  # 速度太快
                # 因为是找左边界,所以若相等,更新右边界
                r = speed - 1
        return l

###################################

class Solution(object):
    def minEatingSpeed(self, piles, h):
        """
        :type piles: List[int]
        :type h: int
        :rtype: int
        """
        import math
        def can_finish(piles,speed):
            time=0
            for i in piles:
                time+=math.ceil((i+0.0)/speed)
            return True if  time<=h else False

        l=1
        r=max(piles)
        while l<=r:
            mid=l+(r-l)//2
            if can_finish(piles,mid):
                r = mid - 1
            else:
                l = mid + 1
        return l
class Solution {
public:
    int canFinish(vector<int> &piles, int speed) {
        int time = 0;
        for (int &i:piles) {
            time += ceil(i / (speed+0.0));
//            time += ceil(i / float(speed));
        }
        return time;
    }

    int minEatingSpeed(vector<int> &piles, int h) {
        int l = 1;
        int r = *max_element(piles.begin(), piles.end());

       while (l <= r) {
           int speed = l + (r - l) / 2;
           if (canFinish(piles, speed) > h) {l = speed + 1;}
           else {
               r = speed - 1;
           }
       }
        return l;
    }
};

1011.在D天内送达包裹的能力

与上题思路相同,只是

  • cap 的最小值和最大值分别为 max(weights)sum(weights)
  • 按照有无超过容量来更新完成的天数d
class Solution(object):
    def shipWithinDays(self, weights, D):
        """
        :type weights: List[int]
        :type D: int
        :rtype: int
        """
        # 当前capacity下完成的天数
        def canFinish(weights,cap):
            cur_w=0
            d=1
            for i in weights:
                if cur_w+i>cap: # 超过容量了,放不下,天数加1,当前容量更新为i
                    d+=1
                    cur_w=i
                else:
                    cur_w+=i # 没有超过,当前容量+i
            return d

        # 二分搜索找左边界
        l=max(weights)
        r=sum(weights)
        while l<=r:
            cap=l+(r-l)//2
            if canFinish(weights, cap)>D:
                l=cap+1
            elif canFinish(weights, cap)<=D:
                r=cap-1
        return l

   转载规则


《第四章:如何运用二分查找算法》 M 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
第四章:如何高效解决接雨水问题 第四章:如何高效解决接雨水问题
labuladong 如何高效解决接雨水问题 42. 接雨水我们开两个数组 l_max 和 r_max 充当备忘录 l_max[i] 表示位置 i 左边最高的柱子高度(包括本身在内,正着遍历), r_max[i] 表示位置 i 右边最高的
2020-08-17
下一篇 
第四章:如何高效寻找素数 第四章:如何高效寻找素数
labuladong如何高效寻找素数 204. 计数质数统计所有小于非负整数 n 的质数的数量 初始化时,给每个位置立一个flag,并初始化为1 遍历时,对于i而言: 如果这个位置的flag为1,说明数字 i 没有被比 i 小的数整除过
2020-08-17
  目录