一种可行解,但是遇到n很大时会造成内存溢出:
class Solution {
/*public int help(int n, int turn){
if(n <= 3){
return turn + 1;
}
int A = help(n - 1, turn + 1);
if(A % 2 != 0){
return A;
}
int B = help(n - 2, turn + 1);
if(B % 2 != 0){
return B;
}
int C = help(n - 3, turn + 1);
if(C % 2 != 0){
return C;
}
return 0;
}
public boolean canWinNim(int n) {//问题性质类似于Ugly Number,有点动态规划的意思
//如何解决堆栈溢出?将重复的记录下来?
int res = help(n, 0);
if(res % 2 != 0){
return true;
}
else{
return false;
}
}*/
//思路来源,一步步分析k=1,2,3...的情况,发现规律(在没有思路时可以这样做)
//借用存储结果,实际上是一个递推的做法(也算动态规划),用一个isWin[n]数组
//在还剩下k个石头时,求出先手(就是我们要判断的先手的玩家)的isWin[k]为true还是false,一步步往上
public boolean canWinNim(int n){
//让下标从1开始
if(n == 1 || n == 2 || n == 3) return true;//特殊情况单独处理,因为后面是基于大于3的情况
boolean isWin[] = new boolean[n + 1];//求出先手(就是我们要判断的先手的玩家)的isWin[k]为true还是false
for(int i = 1; i <= 3; i++) isWin[i] = true;
for(int i = 4; i <= n; i++){
//先手可以选1,2,3个石头,那么先手选了后,后手就变成先手,现在判断后手有没有可能赢
//只要后手存在一种情况不可能赢时,先手就能赢
if(isWin[i - 1] == false || isWin[i - 2] == false || isWin[i - 3] == false){
isWin[i] = true;
}
else{
isWin[i] = false;
}
}
//数组构造完毕后就可以判断结果了
return isWin[n] == true;
}
}
正确解法(也是利用了上面那种的思路,不过做了一个规律总结):
public class Solution {
public boolean canWinNim(int n){
if(n % 4 == 0)
return false;
else
return true;
}
}