LeetCode之路:292. Nim Game

来源:互联网 发布:javashop b2b2c 源码 编辑:程序博客网 时间:2024/06/10 21:10

一、引言

这是一道非常有趣的题目,有着非常简单的规则,却让我一直没有思考出来,甚至在思考这个问题的同时,还引申到了另一道题上面:台阶问题:斐波那契数列的扩展问题研究,有兴趣了解下的同学可以看看这里。

关于这道题,其实这是一个非常出名的游戏,有着不同的版本,LeetCode上面的这个题目是简化的版本。

这里直接把原题目粘贴过来:

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.

那么,这道题怎么做呢?

二、让我们来一个一个例子分析下这个情景

首先,我们来一个一个举例,举例的过程中,我们要记住,每人最多拿 3 个石头,最少必须拿 1 个石头:

当前的石头总数 先手取多少必胜 后手是否必败 1 1 必败 2 2 必败 3 3 必败 4 1 ~ 3 必胜 5 1 同4个石头的情况类似,只不过先后手更替,此处先手必胜 6 2 同4个石头的情况类似,只不过先后手更替,此处先手必胜 7 3 同4个石头的情况类似,只不过先后手更替,此处先手必胜 8 1 ~ 3 此时不论先手拿多少个,都可以让后手造成先手4个石头总数开局,先手必败 … … …

看上面这个表,我们能看到这么一个规律:

当先手玩家遇到了非4的倍数,可以确保必胜;当先手玩家遇到了4的倍数的时候,后手玩家拿走指定数量的石头数量造成剩余4的倍数的石头数量后,后手玩家必胜。

规律总结出来了,真的非常简单,以至于代码更加简单:

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

哈哈哈,看到了更简单的方法:

class Solution {    bool canWinNim(int n) {        return n % 4;    }}

真是好气啊~~~我思考了这么久都没想出来的问题呢,一行代码解决!

三、总结

其实我一看到这道题,脑海里第一个念头是,怎么跟台阶问题那么像,比如:

有一只青蛙,它一次可以跳 1 阶或者 2 阶台阶,那么请问它跳上 N 阶台阶有多少种走法?

这个问题呢,其实是探讨的石头的拿法,但是这道题并不需要拿法有多少,只需要总结规律是否必胜就行了。

总之,学会分析问题的方法。

To be stronger!

0 0
原创粉丝点击