292_Nim Game

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 己方行动&&石子数量<=3the winner, when the node is 对方行动&&石子数量<=3a 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);
    } 
}

Guess you like

Origin www.cnblogs.com/Mrfanl/p/11695378.html
Recommended