774. 最小化去加油站的最大距离
整数数组 stations
表示 水平数轴 上各个加油站的位置。给你一个整数 k
。
请你在数轴上增设 k
个加油站,新增加油站可以位于 水平数轴 上的任意位置,而不必放在整数位置上。
设 penalty()
是:增设 k
个新加油站后,相邻 两个加油站间的最大距离。
请你返回 penalty()
可能的最小值。与实际答案误差在 10-6
范围内的答案将被视作正确答案。
示例 1:
输入:stations = [1,2,3,4,5,6,7,8,9,10], k = 9 输出:0.50000
示例 2:
输入:stations = [23,24,36,39,46,56,57,65,84,98], k = 1 输出:14.00000
提示:
-
10 <= stations.length <= 2000
-
0 <= stations[i] <= 10^8
-
stations
按严格递增顺序排列 -
1 <= k <= 10^6
做题结果
成功,二分答案,大概 log(1e8)*2e3,合起来大概1e7。 写之前想过贪心,只在最大的元素中间插入加油站。但是如果一个距离中间需要插入多个加油站的情况,就不太好处理了。然后肯定要用到堆。但是用堆的话,和k的关系就比较大了。1e6的nlogn显然超了,不行。如果这题k值很小(1e5的话),就可以堆+贪心过了。
方法:二分答案
1. 最小值估算为0
2. 最大值估算为最大最小的差
3. 二分大概猜一下间距。
4. 两个加油站间距离超过间距的补加油站,如果提供的k个加油站能够补完所有空隙,使得任意两个相邻加油站间的距离小于目标则返回
class Solution {
public double minmaxGasDist(int[] stations, int k) {
int n = stations.length;
double min = 0;
double max = stations[n-1]-stations[0];
while(min+(1.0/1e6)<max){
double mid = (max-min)/2+min;
if(check(stations,mid,k)){
max = mid;
}else{
min = mid;
}
}
return min;
}
private boolean check(int[] stations, double dis,int num){
int n = stations.length;
for(int i = 0; i < n-1&&num>=0; i++){
num-=(int)((stations[i+1]-stations[i])/dis);
}
return num>=0;
}
}