题目的关键在于一个净胜分的思路。也就是说对于某段区间来说,不论当前是玩家 1 还是玩家 2,他都是在试图通过选择左端点的数字或者右端点的数字来击败对手在剩余区间对自己的净胜分。
例如现在玩家 1 面对区间 [i, j] 需要做出选择,那么可以定义 dp[i][j] 代表玩家在当前区间的净胜分。如果玩家 1 选择左端数字,那么玩家 2 就在区间 [i+1, j] 中继续选择,玩家 1 的净胜分为 num[i] - dp[i+1][j] 。另一种情况,如果选择右端数字,那么玩家 1 的净胜分为 num[j] - dp[i][j-1] 。只需要在二者中间选择更大的那个就可以了,因为题目问的是最后玩家 1 有没有可能不输。
代码如下:
const PredictTheWinner = function(nums) {
// create the memorization
const memo = Array(nums.length).fill(0).map(
() => Array(nums.length).fill(Number.MIN_SAFE_INTEGER)
);
const dfs = (l, r) => {
// base case
if (l > r) {
return 0;
}
// return early
if (memo[l][r] !== Number.MIN_SAFE_INTEGER) {
return memo[l][r];
}
// compare and store
memo[l][r] = Math.max(
nums[l] - dfs(l + 1, r),
nums[r] - dfs(l, r - 1)
);
return memo[l][r];
}
return dfs(0, nums.length - 1) >= 0;
};