Maximise the minimum distance. The Last True pattern on a feasibility check — and a great example of how "maximise X" problems flip to binary search.
You have n baskets positioned along a number line at positions position[i]. You want to place m balls into the baskets such that the minimum magnetic force (minimum distance between any two balls) is maximised. Return that maximum minimum distance.
Problems that ask "maximise the minimum X" are almost always Last True binary search. The key reframe:
Instead of asking "what is the optimal placement?", ask: "given a minimum distance D, can we place all m balls with at least D apart?" Binary search on D, find the largest D where the answer is yes.
Sort the positions first. Then greedily place balls: put the first ball at the leftmost position. For each subsequent position, only place a ball there if it is at least D away from the last placed ball. If we can place all m balls this way, D is feasible.
Sort first! The problem doesn't guarantee positions are sorted. Sorting takes O(n log n) but is required for the greedy placement check to work correctly.
Pattern recognition: "Maximise the minimum" → Last True. "Minimise the maximum" → First True (like LC 410 Split Array). These two phrasings are mirrors of each other and both binary search the answer space.
position = [1,2,3,4,7] (sorted), m=3, checking D=3
Last placed = 1. Balls placed = 1.
Too close. Skip.
Too close. Skip.
Place ball 2 here. Last placed = 4. Balls placed = 2.
Place ball 3 here. Balls placed = 3 = m. D=3 is feasible! ✓
class Solution { public int maxDistance(int[] position, int m) { Arrays.sort(position); int n = position.length; int left = 1; int right = position[n - 1] - position[0]; // max possible distance int boundary = 1; while (left <= right) { int mid = left + (right - left) / 2; if (canPlace(position, m, mid)) { // feasible — save and try a larger minimum distance boundary = mid; left = mid + 1; } else { // not feasible — try a smaller distance right = mid - 1; } } return boundary; } private boolean canPlace(int[] pos, int m, int minDist) { int count = 1; // place first ball at pos[0] int lastPlaced = pos[0]; for (int i = 1; i < pos.length; i++) { if (pos[i] - lastPlaced >= minDist) { count++; lastPlaced = pos[i]; if (count == m) return true; // placed all balls } } return count >= m; } }
class Solution: def maxDistance(self, position: list[int], m: int) -> int: position.sort() left = 1 right = position[-1] - position[0] # max possible distance boundary = 1 while left <= right: mid = left + (right - left) // 2 if self.can_place(position, m, mid): # feasible — save and try a larger minimum distance boundary = mid left = mid + 1 else: # not feasible — try a smaller distance right = mid - 1 return boundary def can_place(self, pos, m, min_dist): count, last = 1, pos[0] # first ball always at pos[0] for p in pos[1:]: if p - last >= min_dist: count += 1 last = p if count == m: return True return count >= m
Common mistake — forgetting to sort: The greedy placement only works on sorted positions. If you forget to sort first, the feasibility check produces wrong answers and the binary search converges to a wrong result with no error.