有 n
个硬币排成一条线。两个参赛者轮流从右边依次拿走 1 或 2 个硬币,直到没有硬币为止。拿到最后一枚硬币的人获胜。
请判定 先手玩家 必胜还是必败?
若必胜, 返回 true
, 否则返回 false
.
样例
样例 1:
输入: 1
输出: true
样例 2:
输入: 4
输出: true
解释:
先手玩家第一轮拿走一个硬币, 此时还剩三个.
这时无论后手玩家拿一个还是两个, 下一次先手玩家都可以把剩下的硬币拿完.
挑战
O(1) 时间复杂度且O(1) 存储。
解题思路:
动态规划。如果取走1个或者2个石子后,能让剩下的局面先手必败,则当前先手必胜。
设dp[i]表示面对i个硬币时,当前先手是必胜还是必败。走dp[i]步时必胜的前提是要让上一个先手走dp[i-1]或者dp[i-2]处必败。
public class Solution {
/**
* @param n: An integer
* @return: A boolean which equals to true if the first player will win
*/
public boolean firstWillWin(int n) {
// write your code here
//dp[i]表示有i个硬币,玩家是必胜还是必败
boolean[] dp = new boolean[n+1];
if(n >= 1)
dp[1] = true;
if(n >= 2)
dp[2] = true;
for(int i=3; i<=n; i++){
//dp[i]表示自己,则dp[i-1]和dp[i-2]代表对手
//如果对方有一次是败,那我们就能胜
if(dp[i-1] == false || dp[i-2] == false)
dp[i] = true;
else //如果对方都是胜,那我们就必败
dp[i] = false;
}
return dp[n];
}
}