LeetCode OJ 292.Nim Game

时间:2023-03-09 16:41:19
LeetCode OJ 292.Nim Game

You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones.

Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap.

For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend.

对于这个问题,我的第一反应是用递归来解决。递归容易理解,而且代码很简单,如下:

 public class Solution {
public boolean canWinNim(int n) {
if(n<=0) return false;
if(n==1 || n==2 || n==3) return true; if(!canWinNim(n-1)) return true;//如果第一步移除一个,对方是否能赢
if(!canWinNim(n-2)) return true;//如果第一步移除两个,对方是否能赢
if(!canWinNim(n-3)) return true;//如果第一步移除三个,对方是否能赢 return false;
}
}

但是递归的时间复杂度很高,那么如何对这个问题进行改进呢?

看了下别人的答案,如下:

 public class Solution {
public boolean canWinNim(int n) { if(n%4 == 0) return false;
else return true;
}
}

这是为什么呢?n如果能被4整除则不能赢,如果不能整除则能赢,这是为什么呢?

当N=1、2、3时,那么肯定能赢。如果为4时,肯定不会赢。如果N=5、6、7时,先手可以通过取1颗,2颗或者3颗,把问题成:有4颗石头,让对方先手,那么对方肯定输。如果N=8时,无论先手第一次取几颗,对方都有办法把问题变成N=4的规模,那么肯定输。同样,N为9、10、11肯定赢,为12时肯定输。归纳发现:当N为4的倍数时肯定输,不为4的倍数时肯定赢。所以我们就会看到上面的代码。

启发:有些问题的解决不一定要依赖算法,其实找到问题内在的规律解决起来会更迅速简单方便。