2021.4.26 每日leetcode(二分算法)
最简单的就是一个一个试,然后找出船的最小承载量,船的最小承载量必须大于等于任何一个包裹的重量,我们只需要找到包裹的最大重量limit,把它当做船的最小承载量,看看是否满足,
如果满足就返回limit
如果不满足就增加船的承载量limit,继续判断……
public int shipWithinDays(int[] weights, int D) {
//船的最小承载量必须大于等于任何一包裹的重量,不能小于,
//否则这个包裹没法运
int limit = 0;
for (int weight : weights) {
if (weight > limit)
limit = weight;
}
while (true) {
int days = 1;//运输包裹所需要的的天数
int curWeight = 0;//目前船上包裹的重量
for (int weight : weights) {
if (curWeight + weight > limit) {
//如果当前的包裹放到船上,船上的承载量
//大于船的极限,那么当前的包裹就放到明天再运
days++;
curWeight = weight;
} else {
//如果当前的包裹放到船上,还没有达到船
//的承载量,就放到这个船上当天运
curWeight += weight;
}
}
//如果需要的天数大于D,说明不能满足,然后增加
//船的最小承载量limit,进行下一轮循环。
if (days > D) {
limit++;
} else {
return limit;
}
}
}
二分算法
因为船的极限limit必须大于等于包裹的最大重量(假设为left),小于等于所有包裹的重量(假设为right),那么船的最小承载量limit肯定是在[left,right]之间,我们每次枚举left和right之间的值mid,然后在判断,
如果mid不能满足,那么比mid小的都不能满足,这样我们可以排除一半的数量,
如果mid能满足,虽然mid能满足,但不一定是最小的,我们还要继续查找,直到找出最小的承载量即可。
public int shipWithinDays(int[] weights, int D) {
int left = 0;//最大包裹重量,也就是船的最小承载量
int right = 0;//所有包裹的重量,也就是船的最大承载量
for (int weight : weights) {
if (weight > left)
left = weight;
right += weight;
}
//二分法查找
while (left < right) {
//先用中间的值判断是否满足条件
int mid = left + (right - left) / 2;
int days = 1;//需要的天数
int curWeight = 0;//当前船上包裹的重量
for (int weight : weights) {
if (curWeight + weight > mid) {
//如果当前包裹放到船上,超过了船的极限,
//就放到明天再运
days++;
curWeight = weight;
} else {
//如果当前的包裹放到船上,没超过船的极限,
//就把当前的包裹放到船上
curWeight += weight;
}
}
if (days > D) {
//需要的天数超了,说明船的极限小了,
//下一轮循环要增加船的极限
left = mid + 1;
} else {
//需要的天数没超,说明船的极限满足条件,
//然后继续查找更小的满足条件的承载量
right = mid;
}
}
return left;
}
摘自leetcode
right = mid;
}
}
return left;
}
摘自leetcode
作者:sdwwld