Leetcode每日刷题(九)

189 阅读2分钟

题目:除数博弈

描述: 爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。

最初,黑板上有一个数字 N。在每个玩家的回合,玩家需要执行以下操作:

选出任一 x,满足0 < x < NN % x == 0
N - x 替换黑板上的数字 N
如果玩家无法执行这些操作,就会输掉游戏。

只有在爱丽丝在游戏中取得胜利时才返回True,否则返回 false。假设两个玩家都以最佳状态参与游戏。

示例:

输入:2
输出:true
解释:爱丽丝选择 1,鲍勃无法进行操作。
输入:3
输出:false
解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。

解法一:递推

思路: 当先手处于 N = k 状态时, 当做出任意操作,必定使得后手处于 N = m(m < k) 状态, 所以需要找到是否存在一个 m 是必败的状态,就直接执行使得当前数字变为 m ;否则,无论怎样操作,接下来出现的数字都会是先手必胜的,即后手必胜。

可以定义 f[i] 表示 N = i 时,先手处于必胜状态(true) 或必败状态(false),枚举 i(0,i) 中的因数j 看是否存在f[i-j] 为先手必败状态即可

class Solution {
    public boolean divisorGame(int N) {
        boolean[] f = new boolean[N + 5];

        f[1] = false;
        f[2] = true;
        for (int i = 3; i <= N; ++i) {
            for (int j = 1; j < i; ++j) {
                if ((i % j) == 0 && !f[i - j]) {
                    f[i] = true;
                    break;
                }
            }
        }

        return f[N];
    }
}

复杂度分析:

  • 时间复杂度 O(N^2)
  • 空间复杂度 O(N)

解法二:找规律

思路:

  1. 如果 N 为奇数, 约数必为奇数,所以下个数必为偶数。
  2. 如果 N 为偶数,先手只需一直选1,可使得后手一直为奇数,即先手下次还为偶数,直到先手碰到 N = 2 的情况,即必胜

综上所述: N 为奇数, 先手必输; N 为偶数, 先手必胜。

class Solution {
    public boolean divisorGame(int N) {
        return N % 2 == 0;
    }
}

复杂度分析:

  • 时间复杂度 O(1)
  • 空间复杂度 O(1)