Skip to content

Commit 7e42c9a

Browse files
committed
feat: add solutions to lc problem: No.2029
No.2029.Stone Game IX
1 parent 6ffe98e commit 7e42c9a

File tree

6 files changed

+293
-2
lines changed

6 files changed

+293
-2
lines changed

solution/2000-2099/2029.Stone Game IX/README.md

+110-1
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,131 @@ Alice 输掉游戏,因为已移除石子值总和(15)可以被 3 整除,
6666

6767
<!-- 这里可写通用的实现逻辑 -->
6868

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+
6983
<!-- tabs:start -->
7084

7185
### **Python3**
7286

7387
<!-- 这里可写当前语言的特殊实现逻辑 -->
7488

7589
```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)
77107
```
78108

79109
### **Java**
80110

81111
<!-- 这里可写当前语言的特殊实现逻辑 -->
82112

83113
```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+
```
84164

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+
}
85194
```
86195

87196
### **...**

solution/2000-2099/2029.Stone Game IX/README_EN.md

+96-1
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,108 @@ Alice loses the game because the sum of the removed stones (15) is divisible by
6060
### **Python3**
6161

6262
```python
63-
63+
class Solution:
64+
def stoneGameIX(self, stones: List[int]) -> bool:
65+
def check(c):
66+
if c[1] == 0:
67+
return False
68+
c[1] -= 1
69+
turn = 1 + min(c[1], c[2]) * 2 + c[0]
70+
if c[1] > c[2]:
71+
turn += 1
72+
c[1] -= 1
73+
return turn % 2 == 1 and c[1] != c[2]
74+
75+
c = [0] * 3
76+
for s in stones:
77+
c[s % 3] += 1
78+
c1 = [c[0], c[2], c[1]]
79+
return check(c) or check(c1)
6480
```
6581

6682
### **Java**
6783

6884
```java
85+
class Solution {
86+
public boolean stoneGameIX(int[] stones) {
87+
int[] c = new int[3];
88+
for (int s : stones) {
89+
++c[s % 3];
90+
}
91+
int[] t = new int[]{c[0], c[2], c[1]};
92+
return check(c) || check(t);
93+
}
94+
95+
private boolean check(int[] c) {
96+
if (c[1] == 0) {
97+
return false;
98+
}
99+
--c[1];
100+
int turn = 1 + Math.min(c[1], c[2]) * 2 + c[0];
101+
if (c[1] > c[2]) {
102+
--c[1];
103+
++turn;
104+
}
105+
return turn % 2 == 1 && c[1] != c[2];
106+
}
107+
}
108+
```
109+
110+
### **C++**
111+
112+
```cpp
113+
class Solution {
114+
public:
115+
bool stoneGameIX(vector<int>& stones) {
116+
vector<int> c(3);
117+
for (int s : stones) ++c[s % 3];
118+
vector<int> t = {c[0], c[2], c[1]};
119+
return check(c) || check(t);
120+
}
121+
122+
bool check(vector<int>& c) {
123+
if (c[1] == 0) return false;
124+
--c[1];
125+
int turn = 1 + min(c[1], c[2]) * 2 + c[0];
126+
if (c[1] > c[2])
127+
{
128+
--c[1];
129+
++turn;
130+
}
131+
return turn % 2 == 1 && c[1] != c[2];
132+
}
133+
};
134+
```
69135

136+
### **Go**
137+
138+
```go
139+
func stoneGameIX(stones []int) bool {
140+
check := func(c [3]int) bool {
141+
if c[1] == 0 {
142+
return false
143+
}
144+
c[1]--
145+
turn := 1 + min(c[1], c[2])*2 + c[0]
146+
if c[1] > c[2] {
147+
c[1]--
148+
turn++
149+
}
150+
return turn%2 == 1 && c[1] != c[2]
151+
}
152+
c := [3]int{}
153+
for _, s := range stones {
154+
c[s%3]++
155+
}
156+
return check(c) || check([3]int{c[0], c[2], c[1]})
157+
}
158+
159+
func min(a, b int) int {
160+
if a < b {
161+
return a
162+
}
163+
return b
164+
}
70165
```
71166

72167
### **...**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class Solution {
2+
public:
3+
bool stoneGameIX(vector<int>& stones) {
4+
vector<int> c(3);
5+
for (int s : stones) ++c[s % 3];
6+
vector<int> t = {c[0], c[2], c[1]};
7+
return check(c) || check(t);
8+
}
9+
10+
bool check(vector<int>& c) {
11+
if (c[1] == 0) return false;
12+
--c[1];
13+
int turn = 1 + min(c[1], c[2]) * 2 + c[0];
14+
if (c[1] > c[2])
15+
{
16+
--c[1];
17+
++turn;
18+
}
19+
return turn % 2 == 1 && c[1] != c[2];
20+
}
21+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
func stoneGameIX(stones []int) bool {
2+
check := func(c [3]int) bool {
3+
if c[1] == 0 {
4+
return false
5+
}
6+
c[1]--
7+
turn := 1 + min(c[1], c[2])*2 + c[0]
8+
if c[1] > c[2] {
9+
c[1]--
10+
turn++
11+
}
12+
return turn%2 == 1 && c[1] != c[2]
13+
}
14+
c := [3]int{}
15+
for _, s := range stones {
16+
c[s%3]++
17+
}
18+
return check(c) || check([3]int{c[0], c[2], c[1]})
19+
}
20+
21+
func min(a, b int) int {
22+
if a < b {
23+
return a
24+
}
25+
return b
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Solution {
2+
public boolean stoneGameIX(int[] stones) {
3+
int[] c = new int[3];
4+
for (int s : stones) {
5+
++c[s % 3];
6+
}
7+
int[] t = new int[]{c[0], c[2], c[1]};
8+
return check(c) || check(t);
9+
}
10+
11+
private boolean check(int[] c) {
12+
if (c[1] == 0) {
13+
return false;
14+
}
15+
--c[1];
16+
int turn = 1 + Math.min(c[1], c[2]) * 2 + c[0];
17+
if (c[1] > c[2]) {
18+
--c[1];
19+
++turn;
20+
}
21+
return turn % 2 == 1 && c[1] != c[2];
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Solution:
2+
def stoneGameIX(self, stones: List[int]) -> bool:
3+
def check(c):
4+
if c[1] == 0:
5+
return False
6+
c[1] -= 1
7+
turn = 1 + min(c[1], c[2]) * 2 + c[0]
8+
if c[1] > c[2]:
9+
turn += 1
10+
c[1] -= 1
11+
return turn % 2 == 1 and c[1] != c[2]
12+
13+
c = [0] * 3
14+
for s in stones:
15+
c[s % 3] += 1
16+
c1 = [c[0], c[2], c[1]]
17+
return check(c) or check(c1)

0 commit comments

Comments
 (0)