LeetCode 1011. 在 D 天内送达包裹的能力
原题链接
中等
作者:
ITNXD
,
2021-04-26 23:27:09
,
所有人可见
,
阅读 435
简单题解,详细请查看注释
参考代码:
class Solution {
public:
/*
题目要求:将一段划分为最多D段,使得每一段总和的最大值最小! ----> 二分的特点!
证明二分正确性!---> 二分的二段性!
设每一段的总和的最大值最小为x:
>= x :对于大于等于x的位置一定满足要求(要求:可以在D天内运完)
< x :对于小于x的位置一定不满足要求
因此:答案区间具有二段性!
如何求出总和不超过x的情况下最少分成多少段?
数据都是正数,因此使用贪心将每一段尽可能往后走!
贪心正确性证明:
假设贪心解和最优解不一样:
由于贪心解尽可能往后走,因此最优解应该小于贪心解!
使用调整法:我们可以找到二者第一个不同的段,将贪心解多出来的部分减掉,会发现仍然是一个合法的解!
即可以将贪心解调整为最优解!
*/
bool check(vector<int>& w, int D, int x){
int cnt = 1; // 统计分段数
for(int i = 0, s = 0; i < w.size(); i ++){
// 若比上限还大,不合法
if(w[i] > x) return false;
if(s + w[i] > x) cnt ++, s = 0;
s += w[i];
}
return cnt <= D;
}
int shipWithinDays(vector<int>& weights, int D) {
int l = 0, r = 500 * 5000;
while(l < r){
int mid = l + r >> 1;
if(check(weights, D, mid)) r = mid;
else l = mid + 1;
}
return r;
}
};