LeetCode解题分享:1011. Capacity To Ship Packages Within D Days

Problem

A conveyor belt has packages that must be shipped from one port to another within D days.

The i-th package on the conveyor belt has a weight of weights[i]. Each day, we load the ship with packages on the conveyor belt (in the order given by weights). We may not load more weight than the maximum weight capacity of the ship.

Return the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped within D days.

Example 1:

Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5
Output: 15
Explanation:
A ship capacity of 15 is the minimum to ship all the packages in 5 days like this:
1st day: 1, 2, 3, 4, 5
2nd day: 6, 7
3rd day: 8
4th day: 9
5th day: 10
Note that the cargo must be shipped in the order given, so using a ship of capacity 14 and splitting the packages into parts like (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) is not allowed.

Example 2:

Input: weights = [3,2,2,4,1,4], D = 3
Output: 6
Explanation:
A ship capacity of 6 is the minimum to ship all the packages in 3 days like this:
1st day: 3, 2
2nd day: 2, 4
3rd day: 1, 4

Example 3:

Input: weights = [1,2,3,1,1], D = 4
Output: 3
Explanation:
1st day: 1
2nd day: 2
3rd day: 3
4th day: 1, 1

Note:

  1. 1 <= D <= weights.length <= 50000
  2. 1 <= weights[i] <= 500
解题思路

   这是一道乍看上去很难求解的题目,而且数据量也是比较大的,所以很难使用常规的方法求解。这里我们选择二分法求解。

  在二分法中,我们虚招查找某个数据,一半要求数据必须有序,从小到大或者从大到小都可。在这里我们发现给定的数据是无序的,而且也没有办法进行排序,就算排序也无法求解。因此我们考虑对容量(capacity)进行二分求解。

   二分法需要有几个步骤,第一个问题是边界,包括左边界和右边界,第二个是如何处理数据使得舍弃掉一半的无用数据。很明显,我们的左边界至少需要可以装载最大的货物,因此左边界应该取货物重量中的最大值。右边界的取值应该取可以一次性装载所有货物的数值,这个值最小是所有货物重量之和。

   确定完左右边界之后,我们需要考虑如何进行折半查找。在二分查找中,我们总是对左右边界的中点进行考察,假设这个值是mid,然后,我们以这个容量去装载货物,尽可能多装,因为这样可以减少运输的次数(本质上是一种贪心算法。)。如果发现,以这个容量装载货物,运输的次数高于指定的次数,说明我们的容量选小了,我们应该调整左边界指向mid的位置,如果运输的次数低于指定的次数,说明我们的容量选大了,我们应该调整右边界。然后再去重新计算,直到左右边界重合即可。

   代码如下:

class Solution:
    def shipWithinDays(self, weights: List[int], D: int) -> int:
        left, right = max(weights), sum(weights)
        while left < right:
            mid, need, cur = (left + right) // 2, 1, 0
            for w in weights:
                if cur + w > mid:
                    need += 1
                    cur = 0
                cur += w
            if need > D: 
                left = mid + 1
            else: 
                right = mid
        return left
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值