一种可行解,但是遇到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; } }