Leetcode 1552. Magnetic Force Between Two Balls

Problem Summary

In this problem, we have n baskets at distinct positions and m balls. We are asked to distribute the balls in the baskets such that the "minimum magnetic force" between any two balls is as large as possible. The "magnetic force" between two balls is defined as the absolute difference between the positions of the baskets they are in.

We're given an integer array "position" which represents the postions of the baskets (position[i] is the position of the i-th basket), and an integer m representing the number of balls. Our task is to return the maximum possible minimum magnetic force after distributing the balls.

Walkthrough

Given the nature of the problem, a binary search approach would be suitable. Binary search works by repeatedly dividing the search space in half. Each time, it checks whether the middle element is the target. If it isn't, it eliminates either the left half or the right half from consideration, depending on whether the middle element is greater or less than the target. We keep reducing the search space in this manner until we find the target, or until the search space becomes too small (i.e., zero or one).

First, we sort the "position" array in ascending order. Then we define the search range to be between 1 and the difference between the first and last elements of "position". We also initialize a variable to keep track of the maximum force found so far.

Next, we enter a loop where we keep performing binary search until the search range becomes too small. Each time, we calculate a mid-point between the current lower and upper bounds of the search range.

For this mid-point value, we then calculate how many balls it would take to achieve this force using a helper function. If the number of balls required is less than m (the total number of balls), this means that the force is too large, so we reduce the upper bound of the search range to one less than the mid-point. But if the number of balls required is greater than or equal to m, we update the maximum force found so far, and increase the lower bound of the search range to the mid-point.

Once the loop ends, we return the maximum force found.

Example

Consider the position array [1, 2, 3, 4, 7] and m = 3.

Sort the positions: [1, 2, 3, 4, 7] Set the search range: l = 1, r = 7-1 = 6 Enter the loop: mid = 6-(6-1)/2 = 4, numBalls([1, 2, 3, 4, 7], 4) = 2, Since 2 < 3, the force is too large, so reduce r to 4-1 = 3.

Again, mid = 3-(3-1)/2 = 2, numBalls([1, 2, 3, 4, 7], 2) = 3, Since 3 = m, the force is large enough, so increase l to 2.

Lastly, mid = 3-(3-2)/2 = 3, numBalls([1, 2, 3, 4, 7], 3) = 3, As 3 is still equal to m, the force remains large enough, therefore increase l to 3.

Now, l and r have become equal, so the loop ends, and we return l.

Pseudo Code

1
2
3Sort position
4
5Initialize l to 1, r to difference between last and first position
6
7While l < r:
8    mid = r - (r - l) / 2
9    If the number of balls with force mid is >= m:
10        increase l to mid
11    Else:
12        decrease r to mid - 1
13        
14Return l

Python Solution

1
2python
3class Solution:
4 def maxDistance(self, position, m):
5  position.sort()
6  l, r = 1, position[-1] - position[0]
7  
8  while l < r:
9    mid = r - (r - l) // 2
10    if self.numBalls(position, mid) >= m:
11      l = mid
12    else:
13      r = mid - 1
14
15  return l
16
17 def numBalls(self, position, force):
18  balls, prevPosition = 0, -force
19  for pos in position:
20    if pos - prevPosition >= force:
21      balls += 1
22      prevPosition = pos
23  return balls

Java Solution

1
2java
3class Solution {
4 public int maxDistance(int[] position, int m) {
5  Arrays.sort(position);
6  
7  int l = 1, r = position[position.length-1] - position[0];
8
9  while (l < r) {
10    int mid = r - (r - l) / 2;
11    if (numBalls(position, mid) >= m)
12      l = mid;
13    else
14      r = mid - 1;
15  }
16  
17  return l;
18}
19
20 private int numBalls(int[] position, int force) {
21  int balls = 0, prevPosition = -force;
22  for (int pos : position)
23    if (pos - prevPosition >= force) {
24      balls++;
25      prevPosition = pos;
26    }
27    
28  return balls;
29 }
30}

C++ Solution

1
2C++
3class Solution {
4 public:
5  int maxDistance(vector<int>& position, int m) {
6    sort(position.begin(), position.end());
7
8    int l = 1, r = position.back() - position.front();
9
10    while (l < r) {
11      const int mid = r - (r - l) / 2;
12      if (numBalls(position, mid) >= m)
13        l = mid;
14      else
15        r = mid - 1;
16    }
17
18    return l;
19  }
20
21 private:
22  int numBalls(vector<int>& position, int force) {
23    int balls = 0, prevPosition = -force;
24    for (const int pos : position)
25      if (pos - prevPosition >= force) {
26        balls++;
27        prevPosition = pos;
28      }
29    return balls;
30  }
31};

JavaScript Solution

1
2javascript
3class Solution {
4    maxDistance(position, m) {
5        position.sort((a, b) => a - b);
6
7        let l = 1, r = position[position.length-1] - position[0];
8
9        while (l < r) {
10            let mid = r - Math.floor((r - l) / 2);
11            if (this.numBalls(position, mid) >= m)
12                l = mid;
13            else
14                r = mid - 1;
15        }
16        
17        return l;
18    }
19
20    numBalls(position, force) {
21        let balls = 0, prevPosition = -force;
22        for (let i = 0; i < position.length; i++) {
23            if (position[i] - prevPosition >= force) {
24                balls++;
25                prevPosition = position[i];
26            }
27        }
28        
29        return balls;
30    }
31}

In the JavaScript solution, we follow the same approach as the other languages - initializing the low (l) and high (r) variables, setting mid and checking number of balls for that mid value, and then updating l and r based on the result. The sorting method is different than the others due to JavaScript's native array sorting behaving differently, and we use the Math.floor function to ensure the division gives us an integer.

Just as in the pseudocode, our numBalls helper function runs through the sorted position array, and it takes in the current calculated mid force value to determine the number of balls it took to reach that force. If the force is valid (number of balls is less than or equals m), it increases the low boundary otherwise decrease the high boundary. The process continues until low is no longer less than high, at which point the script returns the low value which will be the maximum possible minimum magnetic force between any two balls.


Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.


TA 👨‍🏫