描述
有 n 个硬币排成一条线,每一枚硬币有不同的价值。两个参赛者轮流从任意一边取一枚硬币,知道没有硬币为止。计算拿到的硬币总价值,价值最高的获胜。
请判定 第一个玩家 是输还是赢?
样例
给定数组 A = [3,2,2], 返回 true.
给定数组 A = [1,2,4], 返回 true.
给定数组 A = [1,20,4], 返回 false.
挑战
Follow Up Question:
If n is even. Is there any hacky algorithm that can decide whether first player will win or lose in O(1) memory and O(n) time?
思路
因为不确定从左边拿还是右边拿,所以设置一个二维数组dp[i][j]来表示从i到j这个区间,先手能比后手多拿的分数。
对于某一时刻的状态i,j,只有两个拿硬币的方法,一个是从左,一个是从右,选取其中的最大值,也就是
dp[i][j] = max(values[i]-dp[i+1][j], values[j]-dp[i][j-1])
对于初始状态,dp[i][i] = values[i],因为只有一个硬币。
代码
class Solution {
public:
/**
* @param values: a vector of integers
* @return: a boolean which equals to true if the first player will win
*/
bool firstWillWin(vector<int> &values) {
// write your code here
int n = values.size();
if (n <= 2) return true;
vector<vector<int>> dp;
dp.resize(n, vector<int>(n));
for (int i = 0; i < n; i++)
dp[i][i] = values[i];
for (int i = n-2; i >= 0; i--)
for (int j = i+1; j < n; j++)
dp[i][j] = max(values[i] - dp[i+1][j], values[j]-dp[i][j-1]);
return dp[0][n-1] > 0;
}
};
follow up
如果n是一个偶数,是否可以在On的时间复杂度和O1的空间复杂度内判断出先手的胜负?
暂留