题目描述:
对于这种 最大化的最小 或是 最小化的最大 题目 —— 都可以采用二分的算法来解决
(因为以最大化的最小为例 若ans = x,则对于其他的情况一定都小于x,若有其他的情况能产生使ans > x的则说明x不满足要求)
相当于告诉你了一个答案的区间,每次对中间的数去尝试解决问题,若能解决则左边界右移,若不能右边界左移(另一种情况同理)
所以可以采用对答案所在的区间进行二分来解决
以本题为例:
首先分析 ans 的l,r分别为多少
在那么多个位置中加入m个小球,r = (max-min)/m, l = min(d1,d2,...,dn-1) 【n-1段距离的最小值】
然后对于每一个mid进行check处理,看是否能有这种情况,若不存在,说明mid太大了,所以 r = mid-1; 若存在则 l = mid+1;
最终返回 max(l,r)-1 即可
" 对于check() 可以用贪心来解决——从position[0]开始安置小球,然后下一个安置小球的为位置是上一个位置大ans的第一个位置
若能成功安置全部的小球则返回true,否则返回false "
boolean check(int[] position, int distance, int m) {
int count = 1;
int i = 0;
for (int j = 1; j < position.length; j++) {
if (position[j] - position[i] >= distance) {
i = j;
count++;
if (count >= m) return true;
}
}
return false;
}
二分的算法:
int maxDistance(vector<int>& position, int m) {
if(m > position.size()) return 0;
sort(position.begin(),position.end());
int r = (position[position.size()-1]-position[0])/(m-1);
int l = 0;
for(int i =1;i<position.size();i++)
l = min(l,position[i]-position[i-1]);
// cout<<l<<" "<<r<<endl;
while(l <= r)
{
int mid = (l+r)/2;
if(check(position,mid,m)) l = mid+1;
else r = mid -1;
}
return max(l,r)-1;
}
相似题目:778. 水位上升的泳池中游泳