A conveyor belt has packages that must be shipped from one port to another within D
days.
The ith 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
Constraints:
1 <= D <= weights.length <= 5 * 104
1 <= weights[i] <= 500
這道題說是有一條傳送帶在運送包裹貨物,每個包裹有各自的重量,每天要把若干包裹運送到貨輪上,貨輪有特定的承載量,要求在給定的D天內將所有貨物裝上貨輪,問船的最小載重量是多少。首先來分析,由於船的載重量是固定的,而包裹在傳送帶上又只能按照順序上傳,並不能挑揀,所以一旦加上當前包裹超過了船的載重量,則必須要放棄這個包裹,比較極端的例子就是,假如船的載重量是 50,現在船上已經裝了一個重量為1的包裹,而下一個包裹重量是 50,那么這個包裹只能裝在下一條船上。知道了這一點后,再來分析一下,船的載重量的范圍,先來分析一下最小值,由於所有的包裹都要上船,所以最小的船載重量至少應該是最重的那個包裹,不然上不了船了,而最大的載重量就是包裹的總重量,一條船就能拉走了。所以正確的答案就在這兩個邊界范圍之內,挨個遍歷的話實在有些太不高效了,這里就要祭出二分搜索法了,當算出了中間值 mid 后,利用這個載重量去算需要多少天能運完,然后去和D做比較,如果大於D,說明需要增加載重量,否則減少載重量,最終會終止到正確的結果。具體來看代碼,left 初始化為最大的包裹重量,right 初始化為所有的包裹重量總和。然后進行 while 循環,求出 mid,同時使用兩個變量 cnt 和 cur,分別用來計算需要的天數,和當前貨物的重量,其中 cnt 初始化為1,至少需要一天來運貨物。然后遍歷所有的包裹重量,每次加到 cur,若此時 cur 大於 mid 了,說明當前包裹不能加了,將 cur 重置為當前包裹重量,為下條船做准備,然后 cnt 自增1。遍歷完了之后,判斷若 cnt 大於D,則 left 賦值為 mid+1,否則 right 賦值為 mid,這是博主經常用的一種二分搜索的寫法,可以參見博主之前的總結帖 LeetCode Binary Search Summary 二分搜索法小結,最終返回 left 即可,參見代碼如下:
class Solution {
public:
int shipWithinDays(vector<int>& weights, int D) {
int left = *max_element(weights.begin(), weights.end()), right = accumulate(weights.begin(), weights.end(), 0);
while (left < right) {
int mid = left + (right - left) / 2, cnt = 1, cur = 0;
for (int w : weights) {
cur += w;
if (cur > mid) {
cur = w;
++cnt;
}
}
if (cnt > D) left = mid + 1;
else right = mid;
}
return left;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/1011
參考資料:
https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/