AlgoMaster Logo

Remove Boxes

hardFrequencyUpdated September 21, 2026

Understanding the Problem

We have an array of colored boxes, and we want to remove them in groups of consecutive same-colored boxes to maximize our total score. The scoring is quadratic: removing k boxes at once gives k*k points, not just k. That means it is always better to remove a larger group at once than to remove the same boxes in smaller batches (for example, removing 4 at once gives 16 points, while removing 2 + 2 gives only 8).

This quadratic scoring is what makes the problem tricky. It creates an incentive to delay removing boxes so that separated groups of the same color can be merged together. In Example 1, the three 2s are already adjacent, so we remove them first. But the three 3s are scattered at positions 1, 5, and 7. By removing the boxes between them, we can eventually merge them into one group and remove them together for 9 points instead of 1+1+1 = 3 points.

The order of removals decides the total points, and each removal changes which boxes remain for later removals. That dependency between decisions points to dynamic programming. The difficulty is defining a state that captures enough of the past to make optimal choices.

Key Constraints:

  • 1 <= boxes.length <= 100 -- With n at most 100, an O(n^4) solution runs in time. That budget is large enough to support an interval DP with a third dimension, which the merging behavior turns out to require.
  • 1 <= boxes[i] <= 100 -- Colors are positive integers, so equality of two boxes is a direct comparison. The color values themselves never enter the state.

Approach 1: Brute Force (Backtracking)

Intuition

Try every possible removal order and keep the best total. At each step, scan the array for maximal runs of same-colored boxes. Remove one run, add its score, then recurse on the shorter array that remains. Backtracking over all of these choices finds the maximum.

This simulates the process directly, with no special state representation. It establishes a correct baseline and shows why the obvious formulation is too slow, which motivates the DP that follows.

Algorithm

  1. Given the current list of boxes, find all maximal consecutive groups of the same color.
  2. For each group of size k, compute the score k*k, remove those boxes from the list, and recursively solve the remaining list.
  3. The answer is the maximum of (current group score + recursive result) across all group choices.
  4. Base case: when the list is empty, return 0.

Example Walkthrough

1Initial: boxes = [1, 3, 2, 2, 2, 3, 4, 3, 1], score = 0
0
1
1
3
2
2
3
2
4
2
group of 3 twos
5
3
6
4
7
3
8
1
1/8

Code

The brute force re-explores the same configurations many times, since different removal orders lead to identical remaining arrays. A 2D interval DP dp[l][r] would memoize those subproblems, but it fails here: the score of removing boxes[l] depends on how many same-colored boxes outside [l, r] have already merged onto it, and dp[l][r] cannot represent that. The next approach adds a third dimension to carry exactly that information.

Approach 2: 3D Interval DP with Memoization (Optimal)

Intuition

The DP state gains a third dimension:

dp[l][r][k] = the maximum points from removing boxes[l..r], given that k extra boxes of the same color as boxes[l] are already attached to its left, waiting to be removed together with it.

The k parameter encodes the merging that happens outside the current range. By the time we solve [l, r], earlier removals may have brought same-colored boxes adjacent to boxes[l]. Those boxes are no longer in the array, but their count affects the score we get when we finally remove boxes[l], so the state must carry it.

For any state dp[l][r][k], there are two options:

Option 1: Remove boxes[l] immediately. We remove boxes[l] together with the k extra boxes attached to it. That gives us (k+1)^2 points (k extras + boxes[l] itself = k+1 boxes total). Then we solve dp[l+1][r][0] for the remaining range.

Option 2: Find a matching box and merge. We look for some index m in (l, r] where boxes[m] == boxes[l]. If we first remove everything between l+1 and m-1 (which gives dp[l+1][m-1][0] points), then boxes[m] becomes adjacent to where boxes[l] was. Now we can treat boxes[l] as one more "extra" box attached to boxes[m]. So we solve dp[m][r][k+1].

We take the maximum across all these choices.

Algorithm

  1. Define a 3D memoization table dp[l][r][k] initialized to 0 (uncomputed).
  2. The answer is dp[0][n-1][0]: maximum points from the full array with no extra boxes attached.
  3. For each state dp[l][r][k]:
    • Base case: if l > r, return 0.
    • Optimization: Before branching, absorb any consecutive boxes at the start that match boxes[l]. If boxes[l+1] == boxes[l], increment k and move l forward. This avoids redundant recursion.
    • Option 1 (remove immediately): score = (k+1)^2 + dp[l+1][r][0]
    • Option 2 (merge with a later box): for each m from l+1 to r where boxes[m] == boxes[l], score = dp[l+1][m-1][0] + dp[m][r][k+1]
    • Return the maximum score.
  4. Memoize the result so each state is computed once. A value of 0 marks an uncomputed state, which is safe because any state with l <= r removes at least one box and so returns at least 1.

Example Walkthrough

1dp(0,8,0): boxes[0]=1, look for matching 1 to merge
0
1
l
1
3
2
2
3
2
4
2
5
3
6
4
7
3
8
1
r
match
1/8

Code