• Leetcode 875. 爱吃香蕉的珂珂(中等) 1011. 在D天内送达包裹的能力(中等) 二分查找高级用法


    labuladong讲解

    代码框架

    // 函数 f 是关于自变量 x 的单调函数
    int f(int x) {
        // ...
    }
    
    // 主函数,在 f(x) == target 的约束下求 x 的最值
    int solution(int[] nums, int target) {
        if (nums.length == 0) return -1;
        // 问自己:自变量 x 的最小值是多少?
        int left = ...;
        // 问自己:自变量 x 的最大值是多少?
        int right = ...;
    
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (f(mid) == target) {
                // 问自己:题目是求左边界还是右边界?
                // ...
            } else if (f(mid) < target) {
                // 问自己:怎么让 f(x) 大一点?
                // ...
            } else if (f(mid) > target) {
                // 问自己:怎么让 f(x) 小一点?
                // ...
            }
        }
        return left;
    }

    875. 爱吃香蕉的珂珂(中等)

    题目:

     思路:

    珂珂每小时最多只能吃一堆香蕉,如果吃不完的话留到下一小时再吃;如果吃完了这一堆还有胃口,也只会等到下一小时才会吃下一堆。

    他想在警卫回来之前吃完所有香蕉,让我们确定吃香蕉的最小速度K

    f函数为单调递减,我们要求左侧边界

    class Solution {
    public:
        int minEatingSpeed(vector<int>& piles, int h) {
            //最小速度1
            int left=1;
            //最大速度10^9
            int right=1000000000;
            while(left<=right){
                int mid=left+(right-left)/2;
                //当f<h时,增大f,需要减小k,也就是mid要减小,缩短右边界
                if(f(piles,mid)<h)
                    right=mid-1;
                else if(f(piles,mid)>h)//当f>h时,减小f,需要增大k,也就是mid要增加,左边界增大
                    left=mid+1;
                else
                    right=mid-1;//f==h时,我们求k最小值,也就是最左侧,所以缩小右边界
            }
            return left;
        }
        //单调递减函数,K吃的速度越大,耗时越短
        int f(vector<int>& piles, int k){
            int h=0;
            for(int i=0;i<piles.size();++i){
                //吃完一堆的耗时,不满K按1小时算
                h+=piles[i]/k;
                if(piles[i]%k>0){
                    h++;
                }
            }
            return h;
        }
    };

    1011. 在D天内送达包裹的能力(中等)

    题目:

     思路:

    要在D天内按顺序运输完所有货物,货物不可分割,如何确定运输的最小载重

    f函数为单调递减函数,target显然就是运输天数D,我们要在f(x) == D的约束下,算出船的最小载重

    船的最小载重应该是weights数组中元素的最大值,因为每次至少得装一件货物走,不能说装不下嘛。

    最大载重显然就是weights数组所有元素之和,也就是一次把所有货物都装走

    现在我们确定了自变量x是船的载重能力,f(x)是单调递减的函数,target就是运输总天数限制D,题目要我们计算船的最小载重,也就是x要尽可能小

     这就是搜索左侧边界的二分搜索

    class Solution {
    public:
        int shipWithinDays(vector<int>& weights, int days) {
            int left=0,right=0;
            for(int i=0;i<weights.size();++i){
                left=max(left,weights[i]);
                right+=weights[i];
            }
            while(left<=right){
                int mid=left+(right-left)/2;
                if(f(weights,mid)>days)
                    left=mid+1;
                else if(f(weights,mid)<days)
                    right=mid-1;
                else 
                    right=mid-1;
            }
            return left;
        }
        // 定义:当运载能力为 x 时,需要 f(x) 天运完所有货物
        // f(x) 随着 x 的增加单调递减
        int f(vector<int>& weights, int d){
            int days=0;
            for(int i=0;i<weights.size();){
                //顺序累加重量直到超量
                int w=0;
                while(i<weights.size()){
                    w+=weights[i];
                    if(w>d) break;
                    i++;
                }
                days++;
            }
            return days;
        }
    };
  • 相关阅读:
    Spread Studio中文支持图解
    C#反射实例No.1
    关于XML序列化的简单例子
    将数据结构类型序列化和反序列化(BinaryFormatter类)
    获取计算机名称,IP,MAC地址
    原始套接字发送自定义IP包
    IP包首部格式
    struct和byte[]相互转换(用Marshal类实现)
    图片保存到数据库和从数据库读取图片并显示(C#)
    单词分析器源码
  • 原文地址:https://www.cnblogs.com/zl1991/p/15943873.html
Copyright © 2020-2023  润新知