Problem statement
You are given a sorted array ‘arr’ of length ‘n’, which contains positive integer positions of ‘n’ gas stations on the X-axis.
You are also given an integer ‘k’.
You have to place 'k' new gas stations on the X-axis.
You can place them anywhere on the non-negative side of the X-axis, even on non-integer positions.
Let 'dist' be the maximum value of the distance between adjacent gas stations after adding 'k' new gas stations.
Find the minimum value of dist. (link)
Example:
Input: ‘n' = 7 , ‘k’=6, ‘arr’ = {1,2,3,4,5,6,7}.
Answer: 0.5
Explanation: We can place 6 gas stations at 1.5, 2.5, 3.5, 4.5, 5.5, 6.5. Thus the value of 'dist' will be 0.5. It can be shown that we can't get a lower value of 'dist' by placing 6 gas stations.
Note: You will only see 1 or 0 in the output where: 1 represents your answer is correct. 0 represents your answer is wrong. Answers within 10^-6 of the actual answer will be accepted.
Solution
Placing the new gas stations beyond the existing ones is not feasible since the maximum distance cannot be decreased; it can only be extended. Consider the example where ans = [1,7] and k = 2. In this scenario, we can position the gas stations between the two specified locations, ensuring that the three slots are evenly distributed, and none is greater than any other. To minimize the distances, we strategically position them within equal sectors.
Brute force Approach
To minimize the maximum distance between existing gas stations, we position new gas stations in slots with the maximum distance. After placement, the maximum distance decreases. To allocate incoming gas stations to slots with maximum distance, we maintain an array storing the number of gas stations already in each slot. By knowing the current number of gas stations in a slot, we can calculate the maximum distance between them using a specific formula.
Max distance = Slot_Length/(No new of gas stations + 1)
Example: If the slot is in between 1 to 7 and the no of new gas stations planned is 1.
Slot length = 7-1 = 6
Max distance = 6/(1+1) =3
We take one by one gas station and find out the slot index which has maximum distance available and place it over there.
Later we iterate over through the slots and find out the maximum distance in current configuration and return it.
Time - O(n*k) + O(n)
Space - O(n)
public class Solution {
public static double MinimiseMaxDistance(int []arr, int K){
//Slots available between existing gas stations is arr.length-1
//This stores the number of gas station between each slot
int[] gasStationsPlaced = new int[arr.length-1];
//place each gas station one at a time
for(int station = 1; station<=K; station++){
//Max Distance after placement seen so far
double maxDistance = -1;
int maxIndex = -1;
//Get the index where the current station will be placed in gasStationsPlaced
for(int i=0; i<arr.length-1; i++){
int slotLength = arr[i+1] -arr[i];
double slotLengthAfterPlacement = (double) slotLength/(gasStationsPlaced[i]+1);
if(maxDistance<slotLengthAfterPlacement){
maxDistance = slotLengthAfterPlacement;
maxIndex = i;
}
}
gasStationsPlaced[maxIndex]+=1;
}
//Calculate max distances after the placement of all given gas stations
double ans = -1;
for(int i=0; i<gasStationsPlaced.length;i++){
int slotLength = arr[i+1] -arr[i];
double slotLengthAfterPlacement = (double) slotLength/(gasStationsPlaced[i]+1);
ans = Math.max(ans, slotLengthAfterPlacement);
}
return ans;
}
}
Better Approach
This method mirrors brute force, with the distinction that we organize all pairs consisting of available slot length and the left index of the slot. The top element of the priority queue holds the pair with the longest slot length. We remove this element, position the gas station, update the reduced slot length, and then reintroduce it into the priority queue.
Time - O(nlogn) + O(klogn)
Space - O(n) + O(n)
Insertion into the priority queue takes O(logn) time.
import java.util.*;
public class Solution {
public static double MinimiseMaxDistance(int []arr, int K){
//Slots available between existing gas stations is arr.length-1
//This stores the number of gas station between each slot
int[] gasStationsPlaced = new int[arr.length-1];
PriorityQueue<List<Double>> pq = new PriorityQueue<>((a,b) -> Double.compare(b.get(0), a.get(0)));
for(int i=0; i<gasStationsPlaced.length; i++){
double slotLength = arr[i+1] - arr[i];
pq.add(Arrays.asList(slotLength, (double)i));
}
//place each gas station one at a time
for(int station = 1; station<=K; station++){
int maxIndex = pq.poll().get(1).intValue();
gasStationsPlaced[maxIndex]+=1;
int slotLength = arr[maxIndex+1] - arr[maxIndex];
double reducedLength = (double)slotLength/(gasStationsPlaced[maxIndex]+1);
pq.add(Arrays.asList(reducedLength,(double)maxIndex));
}
return pq.peek().get(0);
}
}
Optimal Approach - Binary Search
In this method, we utilize binary search. Before applying binary search, we determine the range within which the search operation can be executed. This search is conducted within the answer range, which represents the potential minimum distance between configurations.
Answer Range - The answer resides within the range from 0 to the maximum slot length found in the given array, denoted as [0, max slot length].
Core Logic - Given a specific distance, we calculate the number of gas stations required. If the calculated number of gas stations exceeds the required amount, we need to increase the distances; otherwise, we decrease the distance.
Binary Search Logic - We initialize 'low' to 0 and 'high' to the maximum slot length. Then, we determine the midpoint and calculate the number of gas stations required for that midpoint. If the calculated number of gas stations is greater than expected, we update 'low' to the midpoint; otherwise, we update 'high' to the midpoint. This process continues until the difference between 'low' and 'high' is less than 1e-6, indicating that both pointers converge on the same value.
Time - O(n) + O(n) * O(logn)
space - O(1)
import java.util.*;
public class Solution {
public static int getNoOfGasStationsRequried(int[] arr, double dist){
int requiredNo = 0;
for(int i=0; i<arr.length-1; i++){
double slotDistance = arr[i+1] - arr[i];
int expectedGasStations = (int) (slotDistance/dist);
requiredNo+=expectedGasStations;
if(slotDistance == expectedGasStations * dist){
requiredNo-=1;
}
}
return requiredNo;
}
public static double MinimiseMaxDistance(int []arr, int K){
double low = 0;
double high = -1; //max distance between gas stations
for(int i=0; i<arr.length-1; i++){
high = Math.max(high, (double)(arr[i+1]-arr[i]));
}
double maxDifference = 1e-6;
while(high-low > maxDifference){
double mid = (low+high)/2.0;
int noOfGasStations = getNoOfGasStationsRequried(arr, mid);
if(noOfGasStations>K){
low = mid;
}else{
high = mid;
}
}
return high;
}
}