292_Nim Game
I, entitled details
The title means that a given number of rock n, each time the two sides can only take one to three stones, one's own upper hand, asked after a given n, he can not win.
Second, problem-solving approach
The first method (Time Limit Exceeded)
Beginning to get the title, my first idea was to use the problem-solving thinking game tree, when the node status is 己方行动&&石子数量<=3
the winner, when the node is 对方行动&&石子数量<=3
a failure. Because both sides are smart enough, so to take away one step, two, three stones each opponent must win. code show as below:
class Solution {
public boolean canWinNim(int n) {
return canWinNimHelper(n,true);
}
//isSelf==true表示己方行动,false表示对手行动
public boolean canWinNimHelper(int n,boolean isSelf){
if(n<=3&&isSelf) return true;
if(n<=3&&!isSelf) return false;
if(isSelf)
return canWinNimHelper(n-1,!isSelf)
|| canWinNimHelper(n-2,!isSelf)
|| canWinNimHelper(n-3,!isSelf);
else
return canWinNimHelper(n-1,!isSelf)
&& canWinNimHelper(n-2,!isSelf)
&& canWinNimHelper(n-3,!isSelf);
}
}
Not surprisingly, this approach Time Limit Exceeded.
The second method (Memory Limit Exceeded)
This time out because of the above algorithm, the algorithm I observed a moment, you can use the idea of dynamic programming to solve the timeout problem. Specifically algorithm: the now determined whether the stone is composed of n win, take as long as one piece or two pieces or three pieces, the other side will lose the line ( own and each other are the same, dp [i] only indicate that action now in order not win ). So there:
dp[i] = !(dp[i-1]&&dp[i-2]&&dp[i-3])
class Solution {
public boolean canWinNim(int n) {
if(n<=3) return true;
boolean[] dp = new boolean[n+1];
dp[1] = true;dp[2]=true;dp[3]=true;
for(int i=4;i<=n;i++){
dp[i] = !(dp[i-1]&&dp[i-2]&&dp[i-3]);
}
return dp[n];
}
}
This I thought I could accept, but subject to the data is too large, too consuming space dp build arrays, but you can improve the look here: just because the value dp i of i-1, i-2, i-3, so you can leaving only three, this would resolve the problem of memory.
The third method (the Accept)
This method is rather special. As long as n is not divisible by four can win themselves.
Explanation: We know that when n = 1,2,3 we can win, when n = 4 we would lose. When n = 5,6,7, we can remove the corresponding two, three stones when the other side is only four pieces of action, we can win. When n = 8, we will lose. And so on, as long as n is not divisible by four can win themselves.
class Solution {
public boolean canWinNim(int n) {
return !(n%4==0);
}
}