这个题解使用了动态规划的思路。定义状态 dp(i, j, k) 表示考虑区间 [i, j] 中的盒子,并且区间外有 k 个颜色与 boxes[i] 相同的盒子时,能获得的最大积分。状态转移时,可以选择先移除区间 [i, i] 的盒子,获得 (k+1)^2 的积分,再去求解子问题 dp(i+1, j, 0)。也可以选择先移除中间某个位置 m 的盒子(boxes[m] == boxes[i]),获得 dp(i+1, m-1, 0) 的积分,再去求解子问题 dp(m, j, k+1)。在这两种决策中取较大值即可。
时间复杂度: O(n^3)
空间复杂度: O(n^3)
class Solution:
def removeBoxes(self, boxes):
"""
:type boxes: List[int]
:rtype: int
"""
N = len(boxes)
memo = [[[0] * N for _ in range(N) ] for _ in range(N)]
def dp(i, j, k):
if i > j:
return 0
if not memo[i][j][k]:
# 找到第一个与 boxes[i] 颜色不同的盒子位置
index = i
while index + 1 <= j and boxes[index + 1] == boxes[i]:
index += 1
# 更新状态,将与 boxes[i] 颜色相同的盒子数量并入 k
k = k + index - i
i = index
# 决策1:移除区间 [i, i] 的盒子,获得 (k+1)^2 的积分,然后求解子问题 dp(i+1, j, 0)
ans = dp(i + 1, j, 0) + (k + 1) ** 2
# 决策2:先移除中间某个位置 m 的盒子,获得 dp(i+1, m-1, 0) 的积分,然后求解子问题 dp(m, j, k+1)
for index in range(i + 1, j + 1):
if boxes[i] == boxes[index]:
ans = max(ans, dp(i + 1, index - 1, 0) + dp(index, j, k + 1))
memo[i][j][k] = ans
return memo[i][j][k]
return dp(0, N - 1, 0)