0486. 预测赢家【中等】
1. 📝 题目描述
给你一个整数数组 nums。玩家 1 和玩家 2 基于这个数组设计了一个游戏。
玩家 1 和玩家 2 轮流进行自己的回合,玩家 1 先手。开始时,两个玩家的初始分值都是 0。每一回合,玩家从数组的任意一端取一个数字(即,nums[0] 或 nums[nums.length - 1]),取到的数字将会从数组中移除(数组长度减 1 )。玩家选中的数字将会加到他的得分上。当数组中没有剩余数字可取时,游戏结束。
如果玩家 1 能成为赢家,返回 true。如果两个玩家得分相等,同样认为玩家 1 是游戏的赢家,也返回 true。你可以假设每个玩家的玩法都会使他的分数最大化。
示例 1:
txt
输入:nums = [1,5,2]
输出:false
解释:一开始,玩家 1 可以从 1 和 2 中进行选择。
如果他选择 2(或者 1 ),那么玩家 2 可以从 1(或者 2 )和 5 中进行选择。如果玩家 2 选择了 5,那么玩家 1 则只剩下 1(或者 2 )可选。
所以,玩家 1 的最终分数为 1 + 2 = 3,而玩家 2 为 5。
因此,玩家 1 永远不会成为赢家,返回 false。1
2
3
4
5
6
2
3
4
5
6
示例 2:
txt
输入:nums = [1,5,233,7]
输出:true
解释:玩家 1 一开始选择 1。然后玩家 2 必须从 5 和 7 中进行选择。无论玩家 2 选择了哪个,玩家 1 都可以选择 233。
最终,玩家 1(234 分)比玩家 2(12 分)获得更多的分数,所以返回 true,表示玩家 1 可以成为赢家。1
2
3
4
2
3
4
提示:
1 <= nums.length <= 200 <= nums[i] <= 10^7
2. 🎯 s.1 - 区间 DP
c
bool predictTheWinner(int* nums, int numsSize) {
int n = numsSize;
int** dp = (int**)malloc(sizeof(int*) * n);
for (int i = 0; i < n; i++) {
dp[i] = (int*)calloc(n, sizeof(int));
dp[i][i] = nums[i];
}
for (int len = 2; len <= n; len++) {
for (int i = 0; i <= n - len; i++) {
int j = i + len - 1;
int a = nums[i] - dp[i + 1][j];
int b = nums[j] - dp[i][j - 1];
dp[i][j] = a > b ? a : b;
}
}
bool res = dp[0][n - 1] >= 0;
for (int i = 0; i < n; i++) free(dp[i]);
free(dp);
return res;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
js
/**
* @param {number[]} nums
* @return {boolean}
*/
var predictTheWinner = function (nums) {
const n = nums.length
// dp[i][j] 表示在 nums[i..j] 中当前玩家的最大净胜分
const dp = Array.from({ length: n }, () => new Array(n).fill(0))
for (let i = 0; i < n; i++) dp[i][i] = nums[i]
for (let len = 2; len <= n; len++) {
for (let i = 0; i <= n - len; i++) {
const j = i + len - 1
dp[i][j] = Math.max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1])
}
}
return dp[0][n - 1] >= 0
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
py
class Solution:
def predictTheWinner(self, nums: List[int]) -> bool:
n = len(nums)
dp = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] = nums[i]
for length in range(2, n + 1):
for i in range(n - length + 1):
j = i + length - 1
dp[i][j] = max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1])
return dp[0][n - 1] >= 01
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 时间复杂度:
- 空间复杂度:
算法思路:
dp[i][j]表示在nums[i..j]中当前玩家比对手多得的最大分数差- 转移:选左端得
nums[i] - dp[i+1][j],选右端得nums[j] - dp[i][j-1] - 若
dp[0][n-1] >= 0则先手必胜