-
Notifications
You must be signed in to change notification settings - Fork 43
/
CapacityToShipPackagesWithinDDays.java
282 lines (254 loc) · 8.84 KB
/
CapacityToShipPackagesWithinDDays.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
package LeetCodeJava.BinarySearch;
// https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/description/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 1011. Capacity To Ship Packages Within D Days
* <p>
* A conveyor belt has packages that must be shipped from one port to another within days days.
* <p>
* 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.
* <p>
* Return the least weight capacity of the ship that will result in all the packages on the conveyor belt being shipped within days days.
* <p>
* <p>
* <p>
* Example 1:
* <p>
* Input: weights = [1,2,3,4,5,6,7,8,9,10], days = 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
* <p>
* 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:
* <p>
* Input: weights = [3,2,2,4,1,4], days = 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:
* <p>
* Input: weights = [1,2,3,1,1], days = 4
* Output: 3
* Explanation:
* 1st day: 1
* 2nd day: 2
* 3rd day: 3
* 4th day: 1, 1
* <p>
* <p>
* Constraints:
* <p>
* 1 <= days <= weights.length <= 5 * 104
* 1 <= weights[i] <= 500
*/
public class CapacityToShipPackagesWithinDDays {
// V0
// IDEA : BINARY SEARCH
public int shipWithinDays(int[] weights, int days) {
if (weights.length==1){
return weights[0] / days;
}
List<Integer> weightsList = new ArrayList<>();
/**
* NOTE !!!
*
* we get mex weight, and total weight from weights array
*/
int maxWeight = 0;
int totalWeight = 0;
for (int w : weights){
weightsList.add(w);
maxWeight = Math.max(maxWeight, w);
totalWeight += w;
}
/**
* NOTE !!!
*
* we use mex weight, and total weight as
* left, and right pointer of binary search
*
* (not mex, smallest weight or anything else)
* (since we want to get the least weight capacity within D days)
*/
int left = maxWeight;
int right = totalWeight;
// binary search
while(right > left){
int mid = (left + right) / 2;
int calculatedDays = getDays(weightsList, mid);
System.out.println(">>> mid = " + mid + ", maxWeight = " + maxWeight + ", totalWeight = " + totalWeight);
// need to return max possible speed within D days
if (calculatedDays <= days){
right = mid;
}else{
left = mid+1;
}
}
return left; // ??? or return mid
}
private int getDays(List<Integer> weightsList, int speed){
int cur = 0;
int days = 0;
for (Integer w :weightsList){
if (cur + w <= speed){
cur += w;
}else{
days += 1;
cur = w;
}
}
if (cur > 0){
days += 1;
}
System.out.println(">>> speed = " + speed + ", days = " + days);
return days;
}
// V0
// IDEA : BINARY SEARCH (modified by GPT)
public int shipWithinDays_0_1(int[] weights, int days) {
int maxWeight = 0;
int totalWeight = 0;
// Find the maximum single weight and the total weight
for (int weight : weights) {
maxWeight = Math.max(maxWeight, weight);
totalWeight += weight;
}
// Binary search between maxWeight (minimum capacity) and totalWeight (maximum capacity)
int left = maxWeight;
int right = totalWeight;
while (left < right) {
int mid = left + (right - left) / 2;
int calculatedDays = getShipDays(mid, weights);
/** NOTE !!!!
*
* we CAN'T return result directly if calculatedDays == days,
* since what this problem wants is : minimum capacity that can move all goods
* so, instead of return directly, we need to KEEP FINDING smaller possible capacity
*/
// if (calculatedDays==days){
// return mid;
// }
if (calculatedDays <= days) {
// NOTE !!! If we can ship within 'days', try for a smaller capacity
right = mid;
} else {
// If it takes more than 'days', we need a larger capacity
left = mid + 1;
}
}
// can return right as well
return left; // Left and right will converge to the minimum valid capacity
}
private int getShipDays(int capacity, int[] weights) {
int curSum = 0;
int days = 1; // Start with 1 day
for (int weight : weights) {
if (curSum + weight > capacity) {
// If adding the current weight exceeds capacity, ship on a new day
days++;
curSum = 0;
}
curSum += weight;
}
return days;
}
// V1
// IDEA : BINARY SEARCH
// https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/solutions/3216547/day-53-binary-search-easiest-beginner-friendly-sol/
public int shipWithinDays_1(int[] weights, int days) {
int maxWeight = -1, totalWeight = 0;
for (int weight : weights) {
maxWeight = Math.max(maxWeight, weight);
totalWeight += weight;
}
int left = maxWeight, right = totalWeight;
while (left < right) {
int mid = (left + right) / 2;
int daysNeeded = 1, currWeight = 0;
for (int weight : weights) {
if (currWeight + weight > mid) {
daysNeeded++;
currWeight = 0;
}
currWeight += weight;
}
if (daysNeeded > days) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
// V2
// IDEA : BINARY SEARCH
// https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/solutions/256756/java-simple-java-solution-with-explanation/
public int shipWithinDays_2(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;
}
// V3
// IDEA : BINARY SEARCH
// https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/solutions/3216643/clean-codes-full-explanation-binary-search-c-java-python3/
public int shipWithinDays_3(int[] weights, int days) {
int l = Arrays.stream(weights).max().getAsInt();
int r = Arrays.stream(weights).sum();
while (l < r) {
final int m = (l + r) / 2;
if (shipDays(weights, m) <= days)
r = m;
else
l = m + 1;
}
return l;
}
private int shipDays(int[] weights, int shipCapacity) {
int days = 1;
int capacity = 0;
for (final int weight : weights) {
if (capacity + weight > shipCapacity) {
++days;
capacity = weight;
} else
capacity += weight;
}
return days;
}
}