以上两个题考察内容一模一样,均是将数组拆分成一定数量的子数组,求子数组和的最大值,并求解这个最大值的底线为多少?
实现思路:二分法查找
C++版本
class Solution {
public:
int shipWithinDays(vector<int>& weights, int D) {
// 确定二分查找左右边界
int left = *max_element(weights.begin(), weights.end()), right = accumulate(weights.begin(), weights.end(), 0);
while (left < right) {
int mid = (left + right) / 2;
// need 为需要运送的天数
// cur 为当前这一天已经运送的包裹重量之和
int need = 1, cur = 0;
for (int weight: weights) {
if (cur + weight > mid) {
++need;
cur = 0;
}
cur += weight;
}
if (need <= D) {
right = mid;
}
else {
left = mid + 1;
}
}
return left;
}
};
java版本
class Solution {
public int splitArray(int[] nums, int m) {
int left=Arrays.stream(nums).max().getAsInt(),right=Arrays.stream(nums).sum();
while(left<right){
int mid=(right+left)/2;
int need=1,cur=0;
for(int weight:nums){
if(cur+weight>mid){
need++;
cur=0;
}
cur+=weight;
}
if(need<=m){
right=mid;
}
else{
left=mid+1;
}
}
return left;
}
}
再比如这个吃香蕉问题:
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int left=1,right=Arrays.stream(piles).max().getAsInt();
while(left<right){
int mid=(right+left)/2;//mid=K
int need=0;
for(int weight:piles){
if(weight<=mid){
need++;
}
else{
need+=(weight+mid-1)/mid;
}
}
if(need<=h){
right=mid;
}
else{
left=mid+1;
}
}
return left;
}
}