| 
 | 1 | +### 题目描述  | 
 | 2 | + | 
 | 3 | +这是 LeetCode 上的 **[2029. 石子游戏 IX](https://leetcode-cn.com/problems/stone-game-ix/solution/gong-shui-san-xie-fen-qing-kuang-tao-lun-h1oa/)** ,难度为 **中等**。  | 
 | 4 | + | 
 | 5 | +Tag : 「博弈论」  | 
 | 6 | + | 
 | 7 | + | 
 | 8 | + | 
 | 9 | +`Alice` 和 `Bob` 轮流进行自己的回合,`Alice` 先手。每一回合,玩家需要从 `stones` 中移除任一石子。  | 
 | 10 | + | 
 | 11 | +如果玩家移除石子后,导致 所有已移除石子 的价值 总和 可以被 $3$ 整除,那么该玩家就 输掉游戏 。  | 
 | 12 | +如果不满足上一条,且移除后没有任何剩余的石子,那么 `Bob` 将会直接获胜(即便是在 `Alice` 的回合)。  | 
 | 13 | +假设两位玩家均采用 最佳 决策。如果 `Alice` 获胜,返回 `true` ;如果 `Bob` 获胜,返回 `false` 。  | 
 | 14 | + | 
 | 15 | +示例 1:  | 
 | 16 | +```  | 
 | 17 | +输入:stones = [2,1]  | 
 | 18 | +
  | 
 | 19 | +输出:true  | 
 | 20 | +
  | 
 | 21 | +解释:游戏进行如下:  | 
 | 22 | +- 回合 1:Alice 可以移除任意一个石子。  | 
 | 23 | +- 回合 2:Bob 移除剩下的石子。   | 
 | 24 | +已移除的石子的值总和为 1 + 2 = 3 且可以被 3 整除。因此,Bob 输,Alice 获胜。  | 
 | 25 | +```  | 
 | 26 | +示例 2:  | 
 | 27 | +```  | 
 | 28 | +输入:stones = [2]  | 
 | 29 | +
  | 
 | 30 | +输出:false  | 
 | 31 | +
  | 
 | 32 | +解释:Alice 会移除唯一一个石子,已移除石子的值总和为 2 。   | 
 | 33 | +由于所有石子都已移除,且值总和无法被 3 整除,Bob 获胜。  | 
 | 34 | +```  | 
 | 35 | +示例 3:  | 
 | 36 | +```  | 
 | 37 | +输入:stones = [5,1,2,4,3]  | 
 | 38 | +
  | 
 | 39 | +输出:false  | 
 | 40 | +
  | 
 | 41 | +解释:Bob 总会获胜。其中一种可能的游戏进行方式如下:  | 
 | 42 | +- 回合 1:Alice 可以移除值为 1 的第 2 个石子。已移除石子值总和为 1 。  | 
 | 43 | +- 回合 2:Bob 可以移除值为 3 的第 5 个石子。已移除石子值总和为 = 1 + 3 = 4 。  | 
 | 44 | +- 回合 3:Alices 可以移除值为 4 的第 4 个石子。已移除石子值总和为 = 1 + 3 + 4 = 8 。  | 
 | 45 | +- 回合 4:Bob 可以移除值为 2 的第 3 个石子。已移除石子值总和为 = 1 + 3 + 4 + 2 = 10.  | 
 | 46 | +- 回合 5:Alice 可以移除值为 5 的第 1 个石子。已移除石子值总和为 = 1 + 3 + 4 + 2 + 5 = 15.  | 
 | 47 | +Alice 输掉游戏,因为已移除石子值总和(15)可以被 3 整除,Bob 获胜。  | 
 | 48 | +```  | 
 | 49 | + | 
 | 50 | +提示:  | 
 | 51 | +* $1 <= stones.length <= 10^5$  | 
 | 52 | +* $1 <= stones[i] <= 10^4$  | 
 | 53 | + | 
 | 54 | +---  | 
 | 55 | + | 
 | 56 | +### 分情况讨论博弈  | 
 | 57 | + | 
 | 58 | +为了方便,我们用 `A` 来代指 `Alice`,用 `B` 带代指 `Bob`。  | 
 | 59 | + | 
 | 60 | +`A` 只有一种获胜方式,是使得 `B` 在选石子时凑成 $3$ 的倍数;而 `B` 除了能够通过让 `A` 凑成 $3$ 的倍数以外,还能通过让游戏常规结束来获胜。  | 
 | 61 | + | 
 | 62 | +因此整个游戏过程,我们只需要关心「已被移除的石子总和」和「剩余石子个数/价值情况」即可。  | 
 | 63 | + | 
 | 64 | +更进一步的,我们只需关心已被移除的石子总和是否为 $3$ 的倍数,以及剩余石子的价值与已移除石子总和相加是否凑成 $3$ 的倍数即可。   | 
 | 65 | + | 
 | 66 | +所以我们可以按照石子价值除以 $3$ 的余数分成三类,并统计相应数量。  | 
 | 67 | + | 
 | 68 | +不失一般性考虑,某个回合开始前,已移除的石子总和状态为 $x$(共三种,分别为除以 $3$ 余数为 $0$、$1$ 和 $2$,其中当状态为 $0$,且非首个回合时,说明凑成 $3$ 的倍数,游戏结束),剩余石子价值除以 $3$ 的余数 $s$ 分别为 $0$、$1$ 和 $2$。  | 
 | 69 | + | 
 | 70 | +**首先如果当前 $x = 1$ 时,不能选择 $s = 2$ 的石子,否则会导致凑成总和为 $3$ 的倍数而失败;同理 $x = 2$ 时,不能选择 $s = 1$ 的石子;而选择 $s = 0$ 的数字,不会改变 $x$ 的状态,可看做换手操作。**  | 
 | 71 | + | 
 | 72 | +**同时成对的 $s = 0$ 的等价于没有 $s = 0$ 的石子(双方只需要轮流选完这些 $s = 0$ 的石子,最终会回到先手最开始的局面);而选择与 $x$ 相同的 $s$ 会导致 $x$ 改变(即 $x = 1$ 时,选择 $s = 1$ 的石子,会导致 $x = 2$;而 $x = 2$ 时,选 $s = 2$ 的石子,会导致 $x = 1$)。**  | 
 | 73 | + | 
 | 74 | +明确规则后,是分情况讨论的过程:  | 
 | 75 | + | 
 | 76 | +* **$s = 0$ 的石子数量为偶数**:此时等价于没有 $s = 0$ 的石子,我们只需要关心 $s = 1$ 和 $s = 2$ 即可:  | 
 | 77 | +    | 
 | 78 | +    * **$s = 1$ 的石子数量为 $0$**: 这意味着 `A` 开始选择的只能是 $s = 2$,此时交给 `B` 的局面为「$x = 2$、剩余石子只有 $s = 2$」,此时 `B` 只能选 $s = 2$ 的石子,由于 $x = 2$ 且选择的石子 $s = 2$,因此交由回 `A` 的局面为「$x = 1$,剩余是在只有 $s = 2$」,因此游戏继续的话 `A` 必败,同时如果在该过程的任何时刻石子被取完,也是 `B` 直接获胜,即 **`A` 仍为必败**;  | 
 | 79 | +      | 
 | 80 | +    * **$s = 2$ 的石子数量为 $0$**:分析同理,`A` 只能选 $s = 1$,此时交给 `B` 的局面为「$x = 1$、剩余石子只有 $s = 1$」,此时 `B` 只能选 $s = 1$ 的石子,由于 $x = 1$ 且选择的石子 $s = 1$,因此交由回 `A` 的局面为「$x = 2$,剩余是在只有 $s = 1$」,因此游戏继续的话 `A` 必败,同时如果在该过程的任何时刻石子被取完,也是 `B` 直接获胜,即 **`A` 仍为必败**;  | 
 | 81 | + | 
 | 82 | +    * **$s = 1$ 和 $s = 2$ 的石子数量均不为 $0$**:`A` 选数量不是最多的一类石子,`B` 下一回合只能选择相同类型的石子(或是无从选择导致失败),然后游戏继续,最终 `B` 会先进入「只能凑成 $3$ 的倍数」的局面导致失败,即 **`A` 必胜。**  | 
 | 83 | + | 
 | 84 | +* **$s = 0$ 的石子数量为奇数**:此时等价于有一次换手机会,该换手机会必然应用在「对必败局面进行转移」才有意义,因此只有 $s = 1$ 和 $s = 2$ 的石子数量差大于 $2$,`A` 的先手优势不会因为存在换手机会而被转移:  | 
 | 85 | +    | 
 | 86 | +    * **两者数量差不超过 $2$**:此时 `B` 可以利用「对方凑成 $3$ 的倍数必败」规则和「优先使用 $s = 0$ 石子」权利来进入确保自己为必胜态:  | 
 | 87 | +        | 
 | 88 | +        * 举个 🌰,当 $s = 1$ 和 $s = 2$ 的石子数量相等,虽然有 $s = 0$ 的石子,`A` 先手,但是 `A` 的首个回合必然不能选 $s = 0$,否则马上失败结束,因此 `A` 只能选 $s = 1$ 或 $s = 2$,此时 `B`直接选择 $s = 0$ 的石子,交由给 `A` 的局面 $x$ 没有发生改变,`A` 只能选择与首个回合相同的 $s$ 游戏才能继续,因此局面会变为「`B` 先手、$s = 1$ 和 $s = 2$ 的石子数量差为 $2$」,游戏继续,最终 `A` 会先遇到「只能凑成 $3$ 的倍数」的局面,即 **`B` 必胜**。  | 
 | 89 | +          | 
 | 90 | +        * 两者数量差不超过 $2$:此时无论 `A` 选择数量较少或较多的 `s`,`B` 都在第二回合马上使用 $s = 0$ 的石子进行换手,`A` 只能继续选与第一回合相同类型的的石子,游戏才能进行,最终 `A` 会先遇到「只能凑成 $3$ 的倍数」或「石子被取完」的局面,即 **`B` 必胜**。  | 
 | 91 | + | 
 | 92 | +    * **两者数量差超过 $2$** :此时即使 `A` 只要确保第一次选择数量较多的 $s$,不管 `B` 是否使用「优先使用 $s = 0$」的石子,`A` 都有足够次数数量多 $s$ 来抵消换手(或是在 `B` 放弃使用 $s = 0$ 之后马上使用),最终都是 `B` 最先遇到「只能凑成 $3$ 的倍数」的局面,即 **`A` 获胜**。  | 
 | 93 | + | 
 | 94 | +代码:  | 
 | 95 | +```Java  | 
 | 96 | +class Solution {  | 
 | 97 | +    public boolean stoneGameIX(int[] stones) {  | 
 | 98 | +        int[] cnts = new int[3];  | 
 | 99 | +        for (int i : stones) cnts[i % 3]++;  | 
 | 100 | +        return cnts[0] % 2 == 0 ? !(cnts[1] == 0 || cnts[2] == 0) : !(Math.abs(cnts[1] - cnts[2]) <= 2);  | 
 | 101 | +    }  | 
 | 102 | +}  | 
 | 103 | +```  | 
 | 104 | +* 时间复杂度:$O(n)$  | 
 | 105 | +* 空间复杂度:$O(1)$  | 
 | 106 | + | 
 | 107 | +---  | 
 | 108 | + | 
 | 109 | +### 最后  | 
 | 110 | + | 
 | 111 | +这是我们「刷穿 LeetCode」系列文章的第 `No.2029` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。  | 
 | 112 | + | 
 | 113 | +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。  | 
 | 114 | + | 
 | 115 | +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。  | 
 | 116 | + | 
 | 117 | +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。  | 
 | 118 | + | 
0 commit comments