参考的题解都已经在代码中注明了。
看这篇题解得到思路:
https://leetcode-cn.com/problems/remove-boxes/solution/guan-fang-fang-fa-2ji-yi-hua-sou-suo-dong-hua-tu-j/
Java 代码:
public class Solution {
// 参考:https://leetcode-cn.com/problems/remove-boxes/solution/yi-chu-he-zi-by-leetcode/
public int removeBoxes(int[] boxes) {
int[][][] memo = new int[100][100][100];
int len = boxes.length;
return removeBoxes(boxes, memo, 0, len - 1, 0);
}
private int removeBoxes(int[] boxes, int[][][] memo, int left, int right, int k) {
if (left > right) {
return 0;
}
if (memo[left][right][k] != 0) {
return memo[left][right][k];
}
while (left < right && boxes[right] == boxes[right - 1]) {
right--;
k++;
}
memo[left][right][k] = removeBoxes(boxes, memo, left, right - 1, 0) + (k + 1) * (k + 1);
for (int i = left; i < right; i++) {
if (boxes[i] == boxes[right]) {
memo[left][right][k] =
Math.max(memo[left][right][k],
removeBoxes(boxes, memo, left, i, k + 1) + removeBoxes(boxes, memo, i + 1, right - 1, 0));
}
}
return memo[left][right][k];
}
}
Java 代码:
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Solution2 {
// 参考资料:https://leetcode-cn.com/problems/remove-boxes/solution/yuan-chuang-jie-fa-by-inszva-2/
public int removeBoxes(int[] boxes) {
int len = boxes.length;
Map<Integer, Integer> hashMap = new HashMap<>();
int[] next = new int[len];
// 赋值为 len 是有含义的
Arrays.fill(next, len);
// 由于要找右边第 1 个,所以从右边向左边更新
for (int i = len - 1; i >= 0; i--) {
if (hashMap.containsKey(boxes[i])) {
// 正是由于从右向左,保证了它是最新的
next[i] = hashMap.get(boxes[i]);
}
// 记录数字的下标
hashMap.put(boxes[i], i);
}
int[][][] memo = new int[len ][len][len];
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
Arrays.fill(memo[i][j],-1);
}
}
return removeBoxes( memo, next, 0, 0, len - 1);
}
/**
*
* @param memo
* @param next
* @param preSame 前面相同的数有几个
* @param left
* @param right
* @return
*/
private int removeBoxes( int[][][] memo, int[] next, int preSame, int left, int right) {
if (left > right) {
return preSame * preSame;
}
if (memo[preSame][left][right] != -1) {
return memo[preSame][left][right];
}
// 结果至少是这个数字
int res = preSame * preSame;
int index = left;
// 只要它下一个的下标正好是连续的,index 就 + 1
while (next[index] == index + 1 && index + 1 <= right) {
index++;
}
res = Math.max(res, (preSame + index - left + 1) * (preSame + index - left + 1) +
removeBoxes( memo, next, 0, index + 1, right));
int nextJ = next[index];
while (nextJ <= right) {
res = Math.max(res,
removeBoxes(memo, next, 0, index + 1, nextJ - 1)
+ removeBoxes( memo, next, preSame + index - left + 1, nextJ, right));
nextJ = next[nextJ];
}
memo[preSame][left][right] = res;
return res;
}
public static void main(String[] args) {
Solution2 solution2 = new Solution2();
int[] boxes = new int[]{1, 3, 2, 2, 2, 3, 4, 3, 1};
int res = solution2.removeBoxes(boxes);
System.out.println(res);
}
}