546. Remove Boxes


Given several boxes with different colors represented by different positive numbers.
You may experience several rounds to remove boxes until there is no box left. Each time you can choose some continuous boxes with the same color (composed of k boxes, k >= 1), remove them and get k*k points.
Find the maximum points you can get.

Example 1:
Input:

[1, 3, 2, 2, 2, 3, 4, 3, 1]
Output:
23
Explanation:
[1, 3, 2, 2, 2, 3, 4, 3, 1] 
----> [1, 3, 3, 4, 3, 1] (3*3=9 points) 
----> [1, 3, 3, 3, 1] (1*1=1 points) 
----> [1, 1] (3*3=9 points) 
----> [] (2*2=4 points)

Note: The number of boxes n would not exceed 100.


Solution


Approach #1 Brute Force Approach[Time Limit Exceeded]

Algorithm

The brute force approach is very obvious. We try removing every possible element of the given array and calculate the points obtained for the rest of the array in a recursive manner.

Complexity Analysis

  • Time complexity : . be the time to find the solution of n boxes with n different colors, then obviously which results in the time complexity.

  • Space complexity : . The recursive tree goes upto a depth of , with every level consisting of upto elements.


Approach #2 Using DP with Memorization[Accepted]

Algorithm

The problem with the previous approach is that it involves a lot of recomputations. e.g. Consider the array [3, 2, 1, 4, 4, 4]. In this case, we try to remove 3 and calculate the cost for the remaining array, in which we try removing 2 first leading to the point calculation for the subarray [1, 4, 4, 4]. The same happens in the second iteration in which we try to remove 2 first and then remove 3. We can prune the depth of the recursion tree a lot by using memorization.

But the problem of memorization isn't simple in this case. We can't simply use the start and end index of the array to determine the maximum number of points which that subarray will eventually lead to. This is because the points obtained by using the subarray depend not only on the subarray but also on the removals done prior to reaching the current subarray, which aren't even a part of the subarray. e.g. Consider the array [3, 2, 1, 4, 4, 2, 4, 4]. The points obtained for the subarray [3, 2, 1, 4] depend on whether the element 2(index 5) has been already removed or not, since it eventually determines the number of 4's which will be combined together to determine the potential points obtained for the currently considered subarray.

Thus, in order to preserve this information, we need to add another dimension to the memorization array, which tells us how many similar elements are combined together from the end of the current subarray. We make use of a array, which is used to store the maximum number of points that can be obtained for a given subarray with a specific number of similar elements at the end. For an entry in , represents the starting index of the subarray, represents the ending index of the subarray and represents the number of elements similar to the element following it which can be combined to obtain the point information to be stored in . e.g.

This can be better understood with the following example. Consider a subarray . For this subarray, if x_r=6, the entry at represents the maximum points that can be obtained using the subarray if three 6's are appended with the trailing .

Now, let us look at how to fill in the . Consider the same suabrray as mentioned above. For filling in the entry, , we firstly make an initial entry in , which considers the assumption that we will firstly combine the last similar elements and then proceed with the remaining subarray. Thus, the initial entry becomes:

. Here, we combined all the trailing similar elements, so the value 0 is passed as the k value for the recursive function, since no similar elements to the element exist at its end.

But, the above situation isn't the only possible solution. We could obtain a better solution for the same subarray for making the entry into , if we could somehow combine the trailing similar elements with some extra similar elements lying between .

Thus, we look for the elements within , which could be similar to the trailing elements, which in turn are similar to the element. Whenever such an element is found, we check if the new solution could lead to more points by using the same array. If so, we update the entry at .

To get a clearer understanding of the above statment, consider the same subarray again: . If , we could eventually be benefitted by combining and by removing the elements lying between them, since now we can bring similar elements together. By removing the in-between lying elements(, the maximum points we can obtain are given by: . Now, the points obtained from the remaining array are given by: , which is quite clear now.

Thus equation for updation becomes:

.

At the end, the entry for dp[0][n-1][0] gives the required result. In the implementation below, we've made use of calculatePoints function which is simply a recursive function used to obtain the values.

Complexity Analysis

  • Time complexity : array of size is filled.

  • Space complexity : array is of size .


Analysis written by: @vinod23