IOS 算法(基础篇) ----- 除数博弈

a和b一起玩游戏,他们轮流行动。a先手开局。
最初,给定一个数字 N 。在每个玩家的回合,玩家需要执行以下操作:
选出任一 x,满足 0 < x < N 且 N % x == 0 。
用 N - x 替换黑板上的数字 N 。
如果玩家无法执行这些操作,就会输掉游戏。

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

例如:

N = 2 返回: true 因为 0 < x < 2, a选择 1,b无法进行操作。

N = 3 返回: true 因为 0 < x < 3, a选择 1,0 < x < 2接着 b选择1, a无法进行操作。

解题思路:

这道题的算法并不难, 准确说很简洁很简单, 它的难点在于思路

这里有个规则需要留意一下
选出任一 x,满足 0 < x < N 且 N % x == 0
是的, 要求 N除以x余数为0

接下来, 我们先看下有没有规律

N = 1, 0 < x < 1 a 败
N = 2, 0 < x < 2 a 胜 a拿1, b无法执行
N = 3, 0 < x < 3 a 败 a只能拿1, b拿1, a无法执行
N = 4, 0 < x < 4 a 败 a能拿1, 2, 这里a拿1, 重复N=3时, b无法执行
N = 5, 0 < x < 5 a 败 a只拿1, 重复N=4时, a无法执行
...
我们可以发现
N为奇数时, a先手, a败
N为偶数时, a先手, a胜

接下来我们证明一下 是否成立

N = 1, N = 2 时结论成立
N > 2 时, 假设法, 假设 N <= k 时结论成立, 则 N = k + 1 时
① 如果k是偶数, 则 k + 1 是奇数, 此时 x 为 k + 1 的因数, x只能为奇数(因为 奇数*奇数 才能为奇数),
奇数 - 奇数 = 偶数, 且 k + 1 - x <= k, 轮到b时都是偶数, 因为我们已经假设 N <= k (k是偶数)
结论成立, 即先手必胜, 则 k + 1 为奇数 a败

② 如果k是奇数, k + 1 为偶数, x 奇偶都可以,
当 x 为奇数时 k + 1 - x <= k, 且 k + 1 - x 为奇数, N <= k (k是奇数) 成立, b占有奇数, 则b败 a胜
当 x 为偶数时 k + 1 - x < k, 且 k + 1 - x 为偶数, N <= k (k是奇数) 成立, 此时b占有偶数,处于必胜态,则 a处于必败态。由于题目中说“两玩家都以最佳状态参与游戏”,故此时a应减去一个奇数,a必胜。

其实我们也可以这样想

N如果是奇数,它的约数必然都是奇数;若为偶数,则约数可奇可偶。
无论N 初始为多大的值,游戏最终只会进行到N=2时结束,那么谁轮到 N = 2, 谁就会赢, 因为 N = 1 没发再继续选。

因为是a先手,那么
N若为偶数,a则只需一直选1,使b一直面临N为奇数的情况,这样a稳赢;
N若为奇数,那么a第一次选完之后N必为偶数(奇数约数必然都是奇数),那么b只需一直选1就会稳赢。
综述,判断N是奇数还是偶数,即可得出最终结果!

    func divisorGame(_ N: Int) -> Bool {
         return N % 2 == 0
    }

题目来源:力扣(LeetCode) 感谢力扣爸爸 :)

IOS 算法合集地址

你可能感兴趣的:(IOS 算法(基础篇) ----- 除数博弈)