參考的題解都已經在代碼中註明了。
看這篇題解得到思路:
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);
}
}