3040. 相同分数的最大操作数目 II(1709)

给你一个整数数组 nums ,如果 nums 至少 包含 2 个元素,你可以执行以下操作中的 任意 一个:

  • 选择 nums 中最前面两个元素并且删除它们。
  • 选择 nums 中最后两个元素并且删除它们。
  • 选择 nums 中第一个和最后一个元素并且删除它们。

一次操作的 分数 是被删除元素的和。

在确保 所有操作分数相同 的前提下,请你求出 最多 能进行多少次操作。

请你返回按照上述要求 最多 可以进行的操作次数。

示例 1:

1
2
3
4
5
6
7
输入:nums = [3,2,1,2,3,4]
输出:3
解释:我们执行以下操作:
- 删除前两个元素,分数为 3 + 2 = 5 ,nums = [1,2,3,4] 。
- 删除第一个元素和最后一个元素,分数为 1 + 4 = 5 ,nums = [2,3] 。
- 删除第一个元素和最后一个元素,分数为 2 + 3 = 5 ,nums = [] 。
由于 nums 为空,我们无法继续进行任何操作。

示例 2:

1
2
3
4
5
6
输入:nums = [3,2,6,1,4]
输出:2
解释:我们执行以下操作:
- 删除前两个元素,分数为 3 + 2 = 5 ,nums = [6,1,4] 。
- 删除最后两个元素,分数为 1 + 4 = 5 ,nums = [6] 。
至多进行 2 次操作。

提示:

  • 2 <= nums.length <= 2000
  • 1 <= nums[i] <= 1000

(爆内存)区间dp:递推3维数组写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public int maxOperations(int[] nums) {
int n = nums.length;
// f[i][j][sum]: 对于数组nums[i:j],删除元素和都为sum的前提下,最多进行了多少次操作
int f[][][] = new int[n+1][n+1][2001];
int res = 0;
for (int i = n-2; i >= 0; i--) {
for (int j = i+1; j < n; j++) {
int head = nums[i] + nums[i+1];
int tail = nums[j] + nums[j-1];
int mid = nums[i] + nums[j];
f[i][j][head] = Math.max(f[i][j][head], f[i+2][j][head] + 1);
f[i][j][tail] = Math.max(f[i][j][tail], (j-2 >= 0 ? f[i][j-2][tail] : 0) + 1);
f[i][j][mid] = Math.max(f[i][j][mid], f[i+1][j-1][mid] + 1);
if (i == 0 && j == n-1) {
res = Math.max(res, f[i][j][head]);
res = Math.max(res, f[i][j][tail]);
res = Math.max(res, f[i][j][mid]);
}
}
}
return res;
}
}

区间dp:递推,2维数组,并不需要第3维,因为删除元素和最多只有3种情况,依次考虑即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public int maxOperations(int[] nums) {
int n = nums.length;
// 删除元素和最多只有3种情况
int target[] = new int[3];
target[0] = nums[0] + nums[1];
target[1] = nums[n-1] + nums[n-2];
target[2] = nums[0] + nums[n-1];
int res = 0;
for (int tg : target) {
// f[i][j]: 对于数组nums[i:j]最多进行的操作次数
int f[][] = new int[n+1][n+1];
for (int i = n-2; i >= 0; i--) {
for (int j = i+1; j < n; j++) {
int head = nums[i] + nums[i+1];
int tail = nums[j] + nums[j-1];
int mid = nums[i] + nums[j];
if (head == tg) f[i][j] = Math.max(f[i][j], f[i+2][j] + 1);
if (tail == tg) f[i][j] = Math.max(f[i][j], (j-2 >= 0 ? f[i][j-2] : 0) + 1);
if (mid == tg) f[i][j] = Math.max(f[i][j], f[i+1][j-1] + 1);
}
}
res = Math.max(res, f[0][n-1]);
}
return res;
}
}