3040.相同分数的最大操作数目 II
给你一个整数数组 nums ,如果 nums 至少 包含 2 个元素,你可以执行以下操作中的 任意 一个:
- 选择
nums中最前面两个元素并且删除它们。 - 选择
nums中最后两个元素并且删除它们。 - 选择
nums中第一个和最后一个元素并且删除它们。
一次操作的 分数 是被删除元素的和。
在确保 所有操作分数相同 的前提下,请你求出 最多 能进行多少次操作。
请你返回按照上述要求 最多 可以进行的操作次数。
示例 1:
输入: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:
输入:nums = [3,2,6,1,4]
输出:2
解释:我们执行以下操作:
- 删除前两个元素,分数为 3 + 2 = 5 ,nums = [6,1,4] 。
- 删除最后两个元素,分数为 1 + 4 = 5 ,nums = [6] 。
至多进行 2 次操作。
提示:
2 <= nums.length <= 20001 <= nums[i] <= 1000
题解:
class Solution {
/**
无论减哪两个,中间的序列都是连续的
nums[0] + nums[1]:dfs(2, n - 1)
nums[0] + nums[n - 1]:dfs(1, n - 2)
nums[n - 1] + nums[n - 2]:dfs(0, n - 3)
*/
int[][] memory;
int[] nums;
public int maxOperations(int[] nums) {
this.nums = nums;
int n = nums.length;
memory = new int[n][n];
// 删除前两个
int a = clean(2, n - 1, nums[0] + nums[1]);
// 删除前后各一个
int b = clean(1, n - 2, nums[0] + nums[n - 1]);
// 删除后两个
int c = clean(0, n - 3, nums[n - 1] + nums[n - 2]);
int res = Math.max(a, Math.max(b, c)) + 1;
return res;
}
public int clean(int i, int j, int temp) {
for (int k = 0; k < memory.length; k++) {
Arrays.fill(memory[k], -1);
}
return dfs(i, j, temp);
}
public int dfs(int i, int j, int temp) {
// 递归结束条件
if (i >= j) {
return 0;
}
// 判断对应
if (memory[i][j] != -1) {
// 记忆数组索引ij表示在ij情况下取到的最大的次数
return memory[i][j];
}
int res = 0;
// 删除前两个
if (nums[i] + nums[i + 1] == temp) {
res = Math.max(res, dfs(i + 2, j, temp) + 1);
}
// 删除前后各一个
if (nums[i] + nums[j] == temp) {
res = Math.max(res, dfs(i + 1, j - 1, temp) + 1);
}
// 删除后两个
if (nums[j] + nums[j - 1] == temp) {
res = Math.max(res, dfs(i, j - 2, temp) + 1);
}
return memory[i][j] = res;
}
}