@(labuladong的算法小抄)[二分]
leetcode 1011. 在 D 天内送达包裹的能力
题目描述
解题思路
参考:labuladong的算法小抄P362
参考题解:在D天内送达包裹的能力
class Solution {
public int shipWithinDays(int[] weights, int D) {
/* 寻找左侧边界的框架,区间是[left, right] */
/* 船的最小载重是weights中的最大重量,因为装载的重量不会超过船的最大运载重量 */
int left = getMax(weights), right = getSum(weights);
while (left <= right) {
int mid = left + (right - left) / 2;
/* 船的载重为mid时,如果能在D天内运完,则收缩右边界;否则收缩左边界 */
if (canCarry(weights, mid, D)) {
right = mid - 1;
} else {
left = mid + 1;
}
}
/* 由于D最小为1,所以当left > getSum(weights)时,肯定能够运完,所以不需要判断出界 */
return left;
}
/* 船的载重为carry时,从头到尾遍历包裹,判断能否在d天内运完 */
private boolean canCarry(int[] weights, int carry, int d) {
/* 当前船上剩余的载重 */
int curCarry = carry;
for (int weight : weights) {
/* 如果船上剩余载重不够,当前包裹无法放上去,则剩余天数减一,进入到下一天 */
if (curCarry < weight) {
curCarry = carry;
d--;
}
/* 将包裹放到船上 */
curCarry -= weight;
}
return d > 0;
}
/* 计算nums数组所有元素的和 */
private int getSum(int[] nums) {
int sum = 0;
for (int num : nums)
sum += num;
return sum;
}
/* 计算nums数组中最大的元素 */
private int getMax(int[] nums) {
int max = Integer.MIN_VALUE;
for (int num : nums)
max = Math.max(max, num);
return max;
}
}