LeetCode 1552.
Tags: LeetCode
Question
In the universe Earth C-137, Rick discovered a special form of magnetic force between two balls if they are put in his new invented basket. Rick has n empty baskets, the ith basket is at position[i], Morty has m balls and needs to distribute the balls into the baskets such that the minimum magnetic force between any two balls is maximum.
Rick stated that magnetic force between two different balls at positions x and y is |x - y|.
Given the integer array position and the integer m. Return the required force.
Intuition
From the description, we can know that the answer should be in the range : 0<=answer<=10^9-1
because 1<=x,y<=10^9
.
On my first thought, I wanna use BS to get the answer because the answer is the specific range (meaning we can use BS)
Approach
According to my first thought, my solution should be like this:
- sorting initial array (cuz BS requires sorted array)
- getting a current value by BS
- testing if the value is qualified
- pointer moves left if the value is qualified; otherwise pointer moves right
The rest we need to figure out is: What is the definition of qualification? or How to judge if the value is qualified?.
Here is my answer: Use Greedy Algorithm. First we create a counter
which equals m
. Then we get the first element of sorted array and set it as previous element. Once the |current - previous| >= range(BS generated)
we then set current value as previous element and the counter
minus one. Until the counter
turns to 0 (qualified) or the iteration is done (not qualified).
Complexity
-
Time complexity: O(nlogn)
-
Space complexity: O(1)
Code
import java.util.Arrays;
class Solution {
public int maxDistance(int[] position, int m) {
Arrays.sort(position); //nlogn
int left = 0, right = (position[position.length-1]-position[0]) / (m-1);
while (left <= right) {//logn
int mid = left + (right - left) / 2;
if (!isQualified(position, m, mid)) {//n
right = mid - 1;
}else{
left = mid + 1;
}
}
return left - 1;
}
public boolean isQualified(int[] position, int m, int range) {
m--; // always get the first element
int prev = position[0];
for (int i=0; i<position.length; i++) {
if (position[i]-prev >= range) {
if (--m == 0) { // counter turns to 0
return true;
}
prev = position[i];
}
}
return false;
}
}
Check out the description of these two problems at LC 1552.