LeetCode 每日一题 [2029]石子游戏 IX
一道Medium难度(狗屁)的博弈论题,AC率45.3%(手动狗头)。这道题的难度已经远远超过中等难度了,Hard至少一半没有这个难,而且博弈论属于现代数学的一个分支,是运筹学的子类,多用在金融数学,所以这道题对逻辑思维和数学能力要求很高。引用一下一位大佬的评论:
https://leetcode.com/discuss/general-discussion/1500149/weekly-contest-261 官方把这个题放在了第三题的位置(此题的存在也使得2030题的竞赛分远远超过实际难度),引来了美国站用户的不满,并直接导致了博弈题目从此退出LeetCode平台,周赛第三题在放水的道路上越走越远(第三题难度达不到”中等“的情况,此题之前极其罕见,此题以后我已经见过4次)……
这个题目标“中等”是非常过分的,做不出来很正常,如果实在不会就来题解区学习标准做法,不要轻易气馁~
Alice 和 Bob 再次设计了一款新的石子游戏。现有一行 n 个石子,每个石子都有一个关联的数字表示它的价值。给你一个整数数组 stones ,其中 stones[i] 是第 i 个石子的价值。
Alice 和 Bob 轮流进行自己的回合,Alice 先手。每一回合,玩家需要从 stones 中移除任一石子。
如果玩家移除石子后,导致 所有已移除石子 的价值 总和 可以被 3 整除,那么该玩家就 输掉游戏 。
如果不满足上一条,且移除后没有任何剩余的石子,那么 Bob 将会直接获胜(即便是在 Alice 的回合)。
假设两位玩家均采用 最佳 决策。如果 Alice 获胜,返回 true ;如果 Bob 获胜,返回 false 。
先借一张大佬的逻辑图
由于目标是3的倍数,那么我们可以把石子的价值看做除以3的余数,也就是0,1,2,对应石子的数量分别为nums[0],nums[1],nums[2]。
移除类型0的石子可以看做先后手交换:
- 如果类型 0 的石子的个数为偶数,那么胜负情况等价于没有类型 0 的石子的胜负情况;
- 如果类型 0 的石子个数为奇数,那么胜负情况等价于只有 1 个类型 0 的石子的胜负情况。注意这里不能单纯地等价于「没有类型 0 的石子的胜负情况」的相反情况,这是因为如果所有的石子都被移除完,无论谁移除了最后一个石子,都算 Alice 输。因此如果 Alice 发现自己选择移除类型 1 或 2 的石子不能获胜,于是选择移除类型 0 的石子,并且它不能获胜的原因是「石子会移除完」,那么 Alice 仍然会输。
将类型 的石子考虑完全之后,我们就还剩下类型 和 的石子了。可以发现,为了保证移除石子的和不为 的倍数,操作顺序只有可能为下面的两种情况:
-
如果 Alice 首先移除类型 的石子,那么 Bob 只能移除类型 的石子,在这之后 Alice 只能移除类型 的石子,Bob 同样只能移除类型 的石子。以此类推,移除石子的类型序列为:
-
如果 Alice 首先移除类型 的石子,我们可以类似得到移除石子的类型序列为:
总结
- 如果 的数量为偶数,因为 先手,只要 和 皆大于 即可,则 赢。
- 如果 的数量为奇数,相当于在 和 的序列里面可以插一个 ,因为 Alice 先手,只要 和 之间绝对之差大于 ,则 赢。
解释一下如果 的数量为奇数,为什么是 和 之间绝对之差大于 。
- 首先, 肯定不会选择 ,一定会选择 或者 ,以选 举例来说。
- 选了 ,那么 能选 或者 。
- 如果 选了 ,那么 下轮只能选 ,后面 选 ,所以最后的序列为
1 0 1 2 1 2 1...
,可以看出 的数量必须要比 的数量至少多 。 - 如果 选了 ,那么 下轮可以能选 或者 ,可以枚举 选的情况,可以发现最后的序列和上面类似,都是在 1和2的序列里面插入一个.
- 如果 选了 ,那么 下轮只能选 ,后面 选 ,所以最后的序列为
- 选了 ,和上面同理,结果是和选 相反, 的数量必须要比 的数量至少多 。
这样的话代码就如下:
class Solution {
public boolean stoneGameIX(int[] stones) {
int[] nums = new int[3];
for (int i = 0; i < stones.length; i++) {
nums[stones[i] % 3]++;
}
if (nums[0] % 2 == 0) {
return nums[1] > 0 && nums[2] > 0;
} else {
return nums[1] - nums[2] > 2 || nums[2] - nums[1] > 2;
}
}
}
时间复杂度:O(n)
空间复杂度:O(1)