LeetCode从零单排之一分段——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.

题外话时间:

按例我是要给leetcode上的算法题都加个中文名,但是洋文不好,于是乎就查了一下这个“Nim Game”有没有本来的名字。结果给我来了个“尼姆博弈”。不知道是我的洋文太不好,还是翻译的人洋文太好。每次看到“Game Theory”是翻译成博弈论,我都浑身难受。Game就Game,还博弈。不过话说回来,大陆的翻译质量还是稳胜港台的,不然这个尼姆,搞不好翻译个尼玛。内马尔(Neymar),就是翻译成了尼玛。尼玛博弈!博弈尼玛!我们以后称为“尼姆游戏”好不好?


题解:

这道题是目前接受率最高的题,我发现leetcode上题目也经常变,所以我以后也就不排序了,逮到哪题来哪题。这题确实是不难的,你硬想想就知道了。每次你可以拿的范围是1-3个,于是乎,如果轮到你拿的时候,只要还剩1-3个,你就赢了。于是乎,你应该有这种敏感,4是一个极其关键的数字。4恰好是大于你可以拿的范围的最小的数,然后继续想,如果你的对手可以拿的时候,剩多少个,才能保证你一定赢呢?这个数一定是大于3的!大于3的第一个数,是4,而4,就可以!无论是对手拿一个还是拿三个,剩的石子一定是1-3,正好是你的拿的范围。于是乎,如果能保证你留给对手的是四个,你就赢定了。说到这里,稍微写过点代码的人,都知道,只要留4的倍数,就赢了。你只要有一点迭代的思想就行了,没有的话代码再多些一点点就行了。

分析一下,按照题设,你是先手。如果是4的倍数,假设是n*4个石子。你无论拿几个,最多三个,拿完之后,都会(N-1)*4 + X个,这个X是1-3范围内的。那么你的对手,只要拿X个,就保证剩下(N-1)*4个石子。这个时候轮到你,你无论怎么拿,你的对手都可以让石子数保证成为4的倍数。最终来到了还剩4个石子的时候,然后你拿,然后就输了。

如果石子不是4的倍数,这相当于什么?就相当于本来石子是4的倍数,你是后手,你对手拿了一次。那么就按照上面的分析,你赢了。

public class Solution {
    public boolean canWinNim(int n) {
        if((n%4)==0){
            return false;
        }
        else return true;
    }
}
(从现在开始不写C艹了,写够啦,开始写Java)。这就是讲道理的代码,是4就输,不是4就赢。有人会说,你这个过程都是什么直觉,猜测,经验。但是实际上,这么简单的题目应该是一眼看出来的。说实话,科学都是先猜后证,所以,大家练练猜,其实蛮重要的,嘿嘿。


秀操作:

上面是讲道理的代码,下面是不讲道理的代码。(这里用c艹,Java比较讲道理,很多底层的东西不给你直接转化)

class Solution {
public:
    bool canWinNim(int n) {
        return (3&n);
    }
};
说了不讲道理,那么肯定不分析了。其实就是秀秀操作。

但是我可以给点提示,假设我把题目改了,其他统统不变,改成,如果拿走最后一个的算输,这题怎么做?讲道理,我们应该感觉到,关键数字不是4了,4是拿完了的赢,那么比4多一点,应该是拿完了的输。5?对,就是5,试出来了。这个时候的关键是,你要拿的就剩一个给对手,让对手不得不拿,你就赢了。剩五个给对面拿,无论是对面拿1还是3,你都可以拿得只剩一个。接下来就自己思考呗。


从零单排第二战

乙未年 丁亥月 甲辰日



你可能感兴趣的:(LeetCode)