题目大意:
你和你的小伙伴在玩一种游戏,给定 N 个小石头,每次可以拿取 1/2/3 个石头,谁能拿到最后一个就赢了。
给定 n 个石头,你是先手,判断是是否可以赢。
前提:你和小伙伴都不是傻逼
思路:
首先思考没有只能 拿一次的情况下,先手必胜的情况:
n | canWin |
---|---|
1 | 胜 |
2 | 胜 |
3 | 胜 |
从第4个起,就是有交换手了,有4个的时候,无论拿多少个,都会导致对方进入 先手必胜 的条件,就是还剩1,2,3个,所以剩下4个 是 先手必败状态
n | canWin |
---|---|
4 | 败 |
因为之后都是有交换手的,所以我们应该做的是能 确保 对手进入必败的状态,比如有5个的时候,我们可以拿1个,让还剩四个,并且是对手拿,让对手进入先手必败状态
同理,6个的时候我们可以拿2个让对手先手必败状态,7个的时候拿3个。
n | canWin |
---|---|
5 | 胜 |
6 | 胜 |
7 | 胜 |
但是到了 有8个 的情况下,无论我们那1,2,3个都不能让对手在他的回合,进入先手必败状态了,所以8是一个 先手必败状态
n | canWin |
---|---|
8 | 败 |
而到9个的时候,我们可以让拿走一个,让对手进入 目前确定了 先手必败状态 — 8个的时候
这样不断的维护,我们可以发现这是一个非常简单的循环问题。
代码
class Solution {
public:
bool canWinNim(int n) {
if(n%4 == 0) return false;
else return true;
// 或者 return n%4;
}
};
总结:
很简单编码,有同学说面试的被问到过