[路飞]_在 D 天内送达包裹的能力

327 阅读2分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战

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

题目

传送带上的包裹必须在 days 天内从一个港口运送到另一个港口。

传送带上的第 i 个包裹的重量为 weights[i]。每一天,我们都会按给出重量(weights)的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。

返回能在 days 天内将传送带上的所有包裹送达的船的最低运载能力。

示例1

输入:weights = [1,2,3,4,5,6,7,8,9,10], days = 5
输出:15
解释:
船舶最低载重 15 就能够在 5 天内送达所有包裹,如下所示:
第 1 天:1, 2, 3, 4, 52 天:6, 73 天:84 天:95 天:10

请注意,货物必须按照给定的顺序装运,因此使用载重能力为 14 的船舶并将包装分成 (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) 是不允许的。

示例2

输入:weights = [3,2,2,4,1,4], days = 3
输出:6
解释:
船舶最低载重 6 就能够在 3 天内送达所有包裹,如下所示:
第 1 天:3, 22 天:2, 43 天:1, 4

题解

二分法

最低运载能力:

  • 下限是 Math.max(单个包裹重量最大值,所有包裹重量/天数)Math.max(单个包裹重量最大值,所有包裹重量/天数),假设此处边界值为 leftleft
  • 上限是所有包裹重量,假设此处边界值为 rightright

找到边界后可以枚举区间 [left,right][left,right] 得到最低载货量

这里注意区间 [left,right][left,right] 是递增区间,最低载货量可以看作目标值。

连续有序区间寻找目标值,熟悉的二分法;

二分法重要的一点是找到分割条件,在本题中,对于任意载货量 kk

  • 如果可以需要大于 dayday 天将传送带上的所有包裹送达的船,需要在 [k+1,right][k+1,right] 区间上查找
  • 否则需要在 [left,k][left,k] 区间寻找

代码

var shipWithinDays = function(weights, D) {
    const len = weights.length;
    let max = 0;
    let sum = 0
    for(let i = 0 ; i < len ; i++){
        sum+=weights[i]
        max = Math.max(max,weights[i])
    }
    let left = Math.max(max,Math.ceil(sum/D));
    let right = sum;
    while(left < right){
        let mid = left + Math.floor((right-left)/2)
        if(helper(mid,D)){
           
            right = mid
        }else{
            left = mid+1
        }
    }
    return left;
    function helper(targe,day){
        let num = 0;
        for(let i = 0;i < len ; i++){
            if(num+weights[i]> targe){
                num = 0;
                day--
            }
            num+=weights[i]
        }
        return day>0
    }
};