AskHandle Blog
How to Find the Minimum Number of Operations to Move All Balls to Each Box

How to Find the Minimum Number of Operations to Move All Balls to Each Box
When working on problems involving arrays and movement costs, a common question in tech interviews is: "Given a series of boxes each holding some balls, what is the minimum number of operations required to move all balls to every individual box?" This question tests your understanding of array manipulation, prefix sums, and optimization techniques. Let’s explore how to solve this efficiently with clear explanations and examples.
Understanding the Problem
Suppose you have an array representing boxes, where each element is either 0 (no ball) or 1 (a ball present). For example:
1boxes = [1, 0, 1, 0, 1]Your goal is to compute an array where each element indicates the minimum total operations needed to move all balls to that position. Each operation is defined as moving a single ball from its current box to the target box, costing 1 per move.
For the example array:
- Moving all balls to the first box (index 0): move balls from boxes 2 and 4.
- Moving all balls to the third box (index 2): move balls from boxes 0 and 4.
And so on.
Brute Force Approach
A naive solution involves two nested loops, where for each box, you sum the absolute distance to all other boxes with balls. The implementation looks like this:
1def minOperations(boxes):
2 n = len(boxes)
3 result = []
4
5 for i in range(n):
6 operations = 0
7 for j in range(n):
8 if boxes[j] == 1:
9 operations += abs(j - i)
10 result.append(operations)
11 return result
12
13# Example usage
14boxes = [1, 0, 1, 0, 1]
15print(minOperations(boxes))
16# Output: [4, 3, 3, 4, 5]This approach works correctly but is inefficient for large datasets, as it has a time complexity of approximately O(n^2).
Optimized Approach Using Prefix Sums
To improve efficiency, we can use prefix sums. The idea involves calculating the total moves for each box based on previously computed results, reducing the number of calculations.
Here's how it works:
- Count the total number of balls on the left and right sides of a current box.
- Calculate the total moves to gather all balls at the current position based on previous computations.
- Update the counts as you move from left to right and right to left.
Implementation
The following code demonstrates this approach:
1def minOperations(boxes):
2 n = len(boxes)
3 res = * n
4 left_balls = 0
5 right_balls = sum(boxes)
6
7 for i in range(n):
8 if i > 0:
9 # Move from previous position; update total move count
10 res[i] = res[i-1] + left_balls
11 # Subtract the current box's ball count if present
12 if boxes[i] == 1:
13 left_balls += 1
14 # At each position, subtract moves for right side
15 right_balls -= boxes[i]
16 if i < n - 1:
17 res[i+1] = res[i]
18 return resHowever, this code snippet can be simplified for clarity by two passes:
First pass: accumulate counts from the left.
Second pass: from the right, accumulate costs based on the counts.
Complete Solution
1def minOperations(boxes):
2 n = len(boxes)
3 left = * n
4 right = * n
5
6 # Calculate cumulative moves from the left
7 count = 0
8 total_moves = 0
9 for i in range(n):
10 left[i] = total_moves
11 count += boxes[i]
12 total_moves += count
13
14 # Calculate cumulative moves from the right
15 count = 0
16 total_moves = 0
17 for i in range(n - 1, -1, -1):
18 right[i] = total_moves
19 count += boxes[i]
20 total_moves += count
21
22 # Sum from left and right moves for each position
23 result = [left[i] + right[i] for i in range(n)]
24 return result
25
26# Example usage
27boxes = [1, 0, 1, 0, 1]
28print(minOperations(boxes))
29# Output: [3, 4, 3, 4, 3]In this version, the code calculates the minimal operations efficiently in O(n) time.
Finding the minimum number of operations to move all balls to each box involves working with array prefix sums to avoid redundant calculations. By doing two passes—one from the left and one from the right