[英]Two player coin game : tracing optimal sequence in dynamic programming
两名玩家轮流选择外币之一。 最后,我们计算两名球员得分之间的差异,假设他们发挥最佳。 例如列表{4,3,2,1},最佳序列将是4,3,2,1。然后我将得到4+2 = 6分,对手4分。 现在我开发了一个算法如下:
我的工作是打印分数,以及索引中的最佳序列。 所以在数组 {4,3,2,1} 中,最佳序列是 0,1,2,3。
最大运行时间和 Memory 不应超过 n^2。 因此,我用自下而上的方法实现了上述算法,这意味着在一个 i*j 表中,根据我的算法,子问题被一一解决,直到唯一的主要问题位于右上角(其中 i = 0 和j = n-1)。 它可以计算分数,但我不知道如何在运行时跟踪最佳序列,因为当我按子问题计算子问题时,只有分数将被保存并用于下一个问题,而导致最终结果的序列结果,很难追溯。
我尝试创建 Pairs 或多维 ArrayList 来记录序列及其对应的 memo[i][j]......好吧,它们工作了,但是所需的 memory 将大于 n^2,这是不允许的在我的任务中。
那么,是否有更好的想法不需要那么多 memory 空间?
任何帮助将不胜感激,干杯!
我的代码:
public int maxGain(int[] values) {
int n = values.length;
int [][] memo = new int[n][n];
for (int i = 0; i < n; i++)
memo[i][i] = values[i];
for (int i = 0, j = 1; j < n; i++, j++)
memo[i][j] = Math.max(values[i], values[j]);
for (int k = 2; k < n; k++) {
for (int i = 0, j = k; j < n; i++, j++) {
int a = values[i] + Math.min(memo[i + 2][j], memo[i + 1][j - 1]);
int b = values[j] + Math.min(memo[i + 1][j - 1], memo[i][j - 2]);
memo[i][j] = Math.max(a, b);
}
}
return memo[0][n - 1];
}
我猜您的问题类似于预测 LeetCode 的获胜者 (486) ,但您需要进行一些小改动:
class Solution {
public boolean maxGain(int[] nums) {
int length = nums.length;
int[][] dp = new int[length][length];
for (int i = 0; i < length; i++)
dp[i][i] = nums[i];
for (int l = 1; l < length; l++)
for (int i = 0; i < length - l; i++) {
int j = i + l;
dp[i][j] = Math.max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1]);
}
return dp[0][length - 1] > -1;
}
}
class Solution:
def max_gain(self, nums):
length = len(nums)
memo = [[-1 for _ in range(length)] for _ in range(length)]
@functools.lru_cache(None)
def f():
def helper(nums, i, j):
if i > j:
return 0
if i == j:
return nums[i]
if memo[i][j] != -1:
return memo[i][j]
cur = max(nums[i] + min(helper(nums, i + 2, j), helper(nums, i + 1, j - 1)),
nums[j] + min(helper(nums, i, j - 2), helper(nums, i + 1, j - 1)))
memo[i][j] = cur
return cur
score = helper(nums, 0, length - 1)
total = sum(nums)
return 2 * score >= total
return f()
对于此链接中提供的第二个解决方案,空间复杂度可能是N
的数量级:
class Solution {
public boolean maxGain(int[] nums) {
if (nums == null)
return true;
int length = nums.length;
int[] dp = new int[length];
for (int i = length - 1; i >= 0; i--) {
for (int j = i; j < length; j++) {
if (i == j)
dp[i] = nums[i];
else
dp[j] = Math.max(nums[i] - dp[j], nums[j] - dp[j - 1]);
}
}
return dp[length - 1] > -1;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.