Nim游戏

题目要求

你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。

你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。

示例:

输入: 4
输出: false 
解释: 如果堆中有 4 块石头,那么你永远不会赢得比赛;
     因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/nim-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


解题思路

如果堆中石头的数量n不能被4整除,那么先手者总是可以赢得Nim游戏的胜利。

如果石头堆中有一块、两块或是三块石头,那么在你的回合,你就可以把全部石子拿走,从而获胜。而如果就像题目描述那样,堆中恰好有四块石头,你就会失败。因为在这种情况下不管你取走多少石头,总会为你的对手留下几块,使得他可以在游戏中打败你。因此,要想获胜,在你的回合中,必须避免石头堆中的石子数为 4 的情况。

同样地,如果有五块、六块、或是七块石头,你可以控制自己拿取的石头数,总是恰好给你的对手留下四块石头,使他输掉这场比赛。但是如果石头堆里有八块石头,你就不可避免地会输掉,因为不管你从一堆石头中挑出一块、两块还是三块,你的对手都可以选择三块、两块或一块,以确保在再一次轮到你的时候,你会面对四块石头。

public class Solution {
    public boolean canWinNim(int n) {
        return (n % 4 != 0);
    }
}

我们可以通过按位与的方式进一步提高时间效率。

由于我们知道位运算比较高效,在某些情况下,当b为2的n次方时,有如下替换公式:
a % b = a & (b-1)(b=2n)
即:a % 2n = a & (2n-1)

public class Solution {
    public boolean canWinNim(int n) {
        return ((n & 3) != 0);
    }
}

复杂度分析

  • 时间复杂度:O(1),只进行了一次检查。
  • 空间复杂度:O(1),没有使用额外空间。

   转载规则


《Nim游戏》 cyyyys 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
数字的补数 数字的补数
题目要求给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。 注意: 给定的整数保证在32位带符号整数的范围内。你可以假定二进制数不包含前导零位。示例 1: 输入: 5 输出: 2 解释: 5的二进制表示为101(没有前导零位),其
2019-09-24
下一篇 
两树之和 两树之和
题目要求给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例: 给定 nums =
2019-09-12
  目录