@@ -66,22 +66,131 @@ Alice 输掉游戏,因为已移除石子值总和(15)可以被 3 整除,
66
66
67
67
<!-- 这里可写通用的实现逻辑 -->
68
68
69
+ 由于我们只关心总和能否被 3 整除,我们可以将 stones 按照模 3 的结果进行分组计数。
70
+
71
+ 根据题意,第一回合不能移除 0,否则直接输掉游戏,因此第一回合只能移除 1 或者 2。我们可以枚举这两种情况,如果其中一种可以让 Alice 获胜就返回 true,否则返回 false。
72
+
73
+ 下面以第一回合移除 1 来说明。在不考虑移除 0 的前提下,后面的移除由于要满足总和不能被 3 整除,因此移除的石子是固定的,整体构成一个 112121212… 循环的序列。
74
+
75
+ 对于 0,由于移除之后不会改变总和模 3 的结果,因此不会改变后续 1 和 2 的移除顺序,所以我们可以在序列的任意非开头位置插入 0。
76
+
77
+ 两人为了不让自己输掉,必然会按照上述序列进行,直到没有石子,或某一方只能移除导致总和被 3 整除的石子时分出胜负。因此我们需要求出让总和不能被 3 整除的最大的回合数,这相当于 112121212... 序列的最长长度,加上 0 的个数。
78
+
79
+ 若该回合数为奇数,且还有剩余石子,那么下一回合要轮到 Bob 移除石子,且他只能移除一枚让总和被 3 整除的石子,于是 Alice 获胜;否则 Bob 获胜。
80
+
81
+ 对于第一回合移除 2 的情况,同样会构成一个 221212121... 循环的序列,做法同上。
82
+
69
83
<!-- tabs:start -->
70
84
71
85
### ** Python3**
72
86
73
87
<!-- 这里可写当前语言的特殊实现逻辑 -->
74
88
75
89
``` python
76
-
90
+ class Solution :
91
+ def stoneGameIX (self , stones : List[int ]) -> bool :
92
+ def check (c ):
93
+ if c[1 ] == 0 :
94
+ return False
95
+ c[1 ] -= 1
96
+ turn = 1 + min (c[1 ], c[2 ]) * 2 + c[0 ]
97
+ if c[1 ] > c[2 ]:
98
+ turn += 1
99
+ c[1 ] -= 1
100
+ return turn % 2 == 1 and c[1 ] != c[2 ]
101
+
102
+ c = [0 ] * 3
103
+ for s in stones:
104
+ c[s % 3 ] += 1
105
+ c1 = [c[0 ], c[2 ], c[1 ]]
106
+ return check(c) or check(c1)
77
107
```
78
108
79
109
### ** Java**
80
110
81
111
<!-- 这里可写当前语言的特殊实现逻辑 -->
82
112
83
113
``` java
114
+ class Solution {
115
+ public boolean stoneGameIX (int [] stones ) {
116
+ int [] c = new int [3 ];
117
+ for (int s : stones) {
118
+ ++ c[s % 3 ];
119
+ }
120
+ int [] t = new int []{c[0 ], c[2 ], c[1 ]};
121
+ return check(c) || check(t);
122
+ }
123
+
124
+ private boolean check (int [] c ) {
125
+ if (c[1 ] == 0 ) {
126
+ return false ;
127
+ }
128
+ -- c[1 ];
129
+ int turn = 1 + Math . min(c[1 ], c[2 ]) * 2 + c[0 ];
130
+ if (c[1 ] > c[2 ]) {
131
+ -- c[1 ];
132
+ ++ turn;
133
+ }
134
+ return turn % 2 == 1 && c[1 ] != c[2 ];
135
+ }
136
+ }
137
+ ```
138
+
139
+ ### ** C++**
140
+
141
+ ``` cpp
142
+ class Solution {
143
+ public:
144
+ bool stoneGameIX(vector<int >& stones) {
145
+ vector<int > c(3);
146
+ for (int s : stones) ++c[ s % 3] ;
147
+ vector<int > t = {c[ 0] , c[ 2] , c[ 1] };
148
+ return check(c) || check(t);
149
+ }
150
+
151
+ bool check(vector<int>& c) {
152
+ if (c[1] == 0) return false;
153
+ --c[1];
154
+ int turn = 1 + min(c[1], c[2]) * 2 + c[0];
155
+ if (c[1] > c[2])
156
+ {
157
+ --c[1];
158
+ ++turn;
159
+ }
160
+ return turn % 2 == 1 && c[1 ] != c[2 ];
161
+ }
162
+ };
163
+ ```
84
164
165
+ ### ** Go**
166
+
167
+ ``` go
168
+ func stoneGameIX (stones []int ) bool {
169
+ check := func (c [3 ]int ) bool {
170
+ if c[1 ] == 0 {
171
+ return false
172
+ }
173
+ c[1 ]--
174
+ turn := 1 + min (c[1 ], c[2 ])*2 + c[0 ]
175
+ if c[1 ] > c[2 ] {
176
+ c[1 ]--
177
+ turn++
178
+ }
179
+ return turn%2 == 1 && c[1 ] != c[2 ]
180
+ }
181
+ c := [3 ]int {}
182
+ for _ , s := range stones {
183
+ c[s%3 ]++
184
+ }
185
+ return check (c) || check ([3 ]int {c[0 ], c[2 ], c[1 ]})
186
+ }
187
+
188
+ func min (a , b int ) int {
189
+ if a < b {
190
+ return a
191
+ }
192
+ return b
193
+ }
85
194
```
86
195
87
196
### ** ...**
0 commit comments