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 <= D <= weights.length <= 50000
1 <= weights[i] <= 500
Accepted
31,440
Submissions
55,451
answer one
Explanation
Given the number of bags,
return the minimum capacity of each bag,
so that we can put items one by one into all bags.
We binary search the final result.
The left bound is max(A),
The right bound is sum(A).
More Good Binary Search Problems
Here are some similar binary search problems.
Also find more explanations.
Good luck and have fun.
Find the Smallest Divisor Given a Threshold
Divide Chocolate
Capacity To Ship Packages In N Days
Koko Eating Bananas
Minimize Max Distance to Gas Station
Split Array Largest Sum
public int shipWithinDays(int[] weights, int D) {
int left = 0, right = 0;
for (int w: weights) {
left = Math.max(left, w);
right += w;
}
while (left < right) {
int mid = (left + right) / 2, need = 1, cur = 0;
for (int w: weights) {
if (cur + w > mid) {
need += 1;
cur = 0;
}
cur += w;
}
if (need > D) left = mid + 1;
else right = mid;
}
return left;
}
@LeonCheng There is no stupid person, I used to fall when I saw these kind of problems, but with practicing two years, now i still got stuck each time with every single problem i encounter, so just keep practicing.
Explanation of this solution:
The key is left = max(weights), right = sum(weights),
which are the minimum and maximum possible weight capacity of the ship.
Therefore the question becomes Binary Search to find the minimum weight capacity of the ship between left and right.
We start from
mid = (left + right) / 2 as our current weight capacity of the ship.
need = days needed == 1
cur = current cargo in the ship == 0
Start put cargo into ship in order.
when need > D, it means the current ship is too small, we modify left = mid + 1 and continue
If all the cargo is successfully put into ships, we might have a chance to find a smaller ship, so let right = mid and continue.
Finally, when our left == right, we reach our answer
answer two
Java binary search
Since we don’t know exactly what the minimum weight is, we can use binary search to approach to the optimal answer.
class Solution {
public int shipWithinDays(int[] weights, int D) {
// use binary search to find the optimal weight
int low = 1, high = 25000000;
while (low <= high) {
int mid = (low + high) / 2;
boolean can = canShip(weights, D, mid);
if (can) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low;
}
// check whether can ship under the given D and capacity
private boolean canShip(int[] weights, int D, int capacity) {
int day = 1, w = 0;
for (int i = 0; i < weights.length; i++) {
if (weights[i] > capacity || day > D) return false;
if (w + weights[i] > capacity) {
w = weights[i];
day++;
} else {
w += weights[i];
}
}
return day <= D;
}
}
answer three
[Java] Simple java solution with explanation
Step1: Find the minimum possible weight i.e. max(largest value in the array, weight on a ship when the weight is evenly distributed)
Step2: Now use it as max limit for a ship and try to fit items.
Step3: If all the items are filled. TADA!! you have your answer. if not increament the current weight and goto Step2.
class Solution {
public int shipWithinDays(int[] weights, int D) {
/*
* Find the least possible capacity of ship. It will be maximum of -> the
* largest item or the weight on one ship if the weight is evenly distributed on
* all the ships i.e. (sum_of_all_items)/(total_ships)
*/
int heaviestItem = weights[0];
int weightSum = 0;
for (int x : weights) {
heaviestItem = Math.max(heaviestItem, x);
weightSum += x;
}
int avgWeightOnShip = (int) weightSum / D;
// Minimum required weight capacity of a ship
int minWeight = Math.max(heaviestItem, avgWeightOnShip);
// Start from minimum possible size to maximum possible
for (int i = minWeight; i <= weights.length * minWeight; i++) {
int[] ship = new int[D];
int index = 0;
// Fill all the ships
for (int j = 0; j < ship.length; j++) {
// Try to fit as many items as possible
while (index < weights.length && ship[j] + weights[index] < i) {
ship[j] += weights[index];
index++;
}
}
if (index == weights.length)
return i - 1;
}
return 0;
}
}
Update 1: Added avgWeightOnShip (thanks to @minnie101) calculation and updated variable names.