两题目一样的意思。
注意:这种题型基本默认你和对手都是选择最优解,也是就是说,你需要在双人都选择最优解时都能够赢。
思路分析:
- 通过递归函数
dfs
计算每个子问题的得分差异,并使用动态规划数组dp
记录已经计算过的结果,避免重复计算。 - 主函数
predictTheWinner
首先检查数组长度是否为偶数,如果是,则第一个玩家总能赢,直接返回true
。 - 初始化动态规划数组,然后调用递归函数计算得分差异。
- 最终判断得分差异是否大于等于0,如果是,则第一个玩家能赢,返回
true
,否则返回false
。
class Solution {
// 递归函数,计算两位玩家之间的得分差异
// i 和 j 表示当前数组 nums 的范围
int dfs(vector<vector<int>>& dp, int i, int j, vector<int>& nums) {
// 基本情况:当 i 和 j 指向相同元素时,返回该元素
if (i == j) {
return nums[i];
}
// 如果 dp[i][j] 已经计算过,直接返回预先计算的结果
if (dp[i][j] != 0) {
return dp[i][j];
}
// 计算当前范围(i,j)的得分差异
dp[i][j] = max(nums[i] - dfs(dp, i + 1, j, nums), nums[j] - dfs(dp, i, j - 1, nums));
return dp[i][j];
}
public:
// 主函数,判断是否第一个玩家能赢
bool predictTheWinner(vector<int>& nums) {
int n = nums.size();
// 如果数组长度为偶数,直接返回true,因为第一个玩家总能赢
if (n % 2 == 0) {
return true;
}
// 初始化动态规划数组
vector<vector<int>> dp(n, vector<int>(n, 0));
// 调用递归函数计算得分差异
dfs(dp, 0, n - 1, nums);
// 如果得分差异大于等于0,则第一个玩家能赢
return dp[0][n - 1] >= 0;
}
};