题目:[1]
给出一些不同颜色的盒子,盒子的颜色由数字表示,即不同的数字表示不同的颜色。你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续 k 个盒子(k >= 1),这样一轮之后你将得到 k*k 个积分。当你将所有盒子都去掉之后,求你能获得的最大积分和。
输入:boxes = [1,3,2,2,2,3,4,3,1]
输出:23
解释:
[1, 3, 2, 2, 2, 3, 4, 3, 1]
----> [1, 3, 3, 4, 3, 1] (3*3=9 分)
----> [1, 3, 3, 3, 1] (1*1=1 分)
----> [1, 1] (3*3=9 分)
----> [] (2*2=4 分)
抛砖引玉
思路
题目的逻辑为:每次移除连续相同字符,求每次移除个数的最大平方和
逻辑复杂的点为移除字符后字符连续情况可能发生变化
移除的思路:指定一点查询与其相同的元素,遇到与其不同的元素时:
每次移除元素均取两种移除方式得到的最大值
实现
特殊情况
/**
* @param {number[]} boxes
* @return {number}
*/
var removeBoxes = function (boxes) {
let len = boxes.length,
dp = Array()
for (let i = 0; i < len; i++) {
dp[i] = new Array(len)
for (let j = 0; j < len; j++) {
dp[i][j] = new Array(len).fill(0)
}
}
function getNum(boxes, dp, i, j, k) {
if (i > j) return 0
// 区间计算过则直接返回
if (dp[i][j][k] != 0) return dp[i][j][k]
// 统计区间内连续子元素数量
while (i > j && boxes[j] === boxes[j - 1]) {
j--
k++
}
// 递归得到指定区间l->j的结果
dp[i][j][k] = getNum(boxes, dp, i, j - 1, 0) + (k + 1) * (k + 1)
// 在区间内枚举可能的存在的子区间
for (let x = i; x < j; x++) {
if (boxes[x] === boxes[j]) {
// dp[i][j][k]保存不同移除顺序下的最大值
dp[i][j][k] = Math.max(
dp[i][j][k],
getNum(boxes, dp, i, x, k + 1) + getNum(boxes, dp, x + 1, j - 1, 0)
)
}
}
return dp[i][j][k]
}
return getNum(boxes, dp, 0, len - 1, 0)
}
参考资料
[1]
题目:: https://leetcode-cn.com/problems/remove-boxes/