Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 52ea485

Browse files
feat: add solutions to lc problem: No.2029 (doocs#3250)
No.2029.Stone Game IX
1 parent 34c9607 commit 52ea485

File tree

7 files changed

+260
-163
lines changed

7 files changed

+260
-163
lines changed

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

Lines changed: 93 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,19 @@ Alice 输掉游戏,因为已移除石子值总和(15)可以被 3 整除,
8484

8585
<!-- solution:start -->
8686

87-
### 方法一
87+
### 方法一:贪心 + 分情况讨论
88+
89+
由于玩家的目标是使得已移除石子的价值总和不能被 3ドル$ 整除,因此我们只需要考虑每个石子的价值对 3ドル$ 的余数即可。
90+
91+
我们用一个长度为 3ドル$ 的数组 $\textit{cnt}$ 维护当前剩余石子的价值对 3ドル$ 的余数的个数,其中 $\textit{cnt}[0]$ 表示余数为 0ドル$ 的个数,而 $\textit{cnt}[1]$ 和 $\textit{cnt}[2]$ 分别表示余数为 1ドル$ 和 2ドル$ 的个数。
92+
93+
在第一回合,Alice 不能移除余数为 0ドル$ 的石子,因为这样会使得已移除石子的价值总和能被 3ドル$ 整除。因此,Alice 只能移除余数为 1ドル$ 或 2ドル$ 的石子。
94+
95+
我们首先考虑 Alice 移除余数为 1ドル$ 的石子的情况。如果 Alice 移除了一个余数为 1ドル$ 的石子,石子 0ドル$ 对石子价值总和对 3ドル$ 的余数不会改变,因此价值对 3ドル$ 的余数为 0ドル$ 的石子可以在任意回合被移除,我们暂时不考虑。所以 Bob 也只能移除余数为 1ドル$ 的石子,之后 Alice 移除余数为 2ドル$ 的石子,依次进行,序列为 1,ドル 1, 2, 1, 2, \ldots$。在这种情况下,如果最终回合数为奇数,且还有剩余石子,那么 Alice 获胜,否则 Bob 获胜。
96+
97+
对于第一回合 Alice 移除余数为 2ドル$ 的石子的情况,我们可以得到类似的结论。
98+
99+
时间复杂度 $O(n),ドル其中 $n$ 是数组 $\textit{stones}$ 的长度。空间复杂度 $O(1)$。
88100

89101
<!-- tabs:start -->
90102

@@ -93,47 +105,46 @@ Alice 输掉游戏,因为已移除石子值总和(15)可以被 3 整除,
93105
```python
94106
class Solution:
95107
def stoneGameIX(self, stones: List[int]) -> bool:
96-
def check(c):
97-
if c[1] == 0:
108+
def check(cnt: List[int]) -> bool:
109+
if cnt[1] == 0:
98110
return False
99-
c[1] -= 1
100-
turn = 1 + min(c[1], c[2]) * 2 + c[0]
101-
if c[1] > c[2]:
102-
turn += 1
103-
c[1] -= 1
104-
return turn % 2 == 1 and c[1] != c[2]
105-
106-
c = [0] * 3
107-
for s in stones:
108-
c[s % 3] += 1
109-
c1 = [c[0], c[2], c[1]]
110-
return check(c) or check(c1)
111+
cnt[1] -= 1
112+
r = 1 + min(cnt[1], cnt[2]) * 2 + cnt[0]
113+
if cnt[1] > cnt[2]:
114+
cnt[1] -= 1
115+
r += 1
116+
return r % 2 == 1 and cnt[1] != cnt[2]
117+
118+
c1 = [0] * 3
119+
for x in stones:
120+
c1[x % 3] += 1
121+
c2 = [c1[0], c1[2], c1[1]]
122+
return check(c1) or check(c2)
111123
```
112124

113125
#### Java
114126

115127
```java
116128
class Solution {
117129
public boolean stoneGameIX(int[] stones) {
118-
int[] c = new int[3];
119-
for (int s : stones) {
120-
++c[s % 3];
130+
int[] c1 = new int[3];
131+
for (int x : stones) {
132+
c1[x % 3]++;
121133
}
122-
int[] t = newint[] {c[0], c[2], c[1]};
123-
return check(c) || check(t);
134+
int[] c2 = {c1[0], c1[2], c1[1]};
135+
return check(c1) || check(c2);
124136
}
125137

126-
private boolean check(int[] c) {
127-
if (c[1] == 0) {
138+
private boolean check(int[] cnt) {
139+
if (--cnt[1] < 0) {
128140
return false;
129141
}
130-
--c[1];
131-
int turn = 1 + Math.min(c[1], c[2]) * 2 + c[0];
132-
if (c[1] > c[2]) {
133-
--c[1];
134-
++turn;
142+
int r = 1 + Math.min(cnt[1], cnt[2]) * 2 + cnt[0];
143+
if (cnt[1] > cnt[2]) {
144+
--cnt[1];
145+
++r;
135146
}
136-
return turn % 2 == 1 && c[1] != c[2];
147+
return r % 2 == 1 && cnt[1] != cnt[2];
137148
}
138149
}
139150
```
@@ -144,21 +155,23 @@ class Solution {
144155
class Solution {
145156
public:
146157
bool stoneGameIX(vector<int>& stones) {
147-
vector<int> c(3);
148-
for (int s : stones) ++c[s % 3];
149-
vector<int> t = {c[0], c[2], c[1]};
150-
return check(c) || check(t);
151-
}
152-
153-
bool check(vector<int>& c) {
154-
if (c[1] == 0) return false;
155-
--c[1];
156-
int turn = 1 + min(c[1], c[2]) * 2 + c[0];
157-
if (c[1] > c[2]) {
158-
--c[1];
159-
++turn;
158+
vector<int> c1(3);
159+
for (int x : stones) {
160+
++c1[x % 3];
160161
}
161-
return turn % 2 == 1 && c[1] != c[2];
162+
vector<int> c2 = {c1[0], c1[2], c1[1]};
163+
auto check = [](auto& cnt) -> bool {
164+
if (--cnt[1] < 0) {
165+
return false;
166+
}
167+
int r = 1 + min(cnt[1], cnt[2]) * 2 + cnt[0];
168+
if (cnt[1] > cnt[2]) {
169+
--cnt[1];
170+
++r;
171+
}
172+
return r % 2 && cnt[1] != cnt[2];
173+
};
174+
return check(c1) || check(c2);
162175
}
163176
};
164177
```
@@ -167,23 +180,48 @@ public:
167180
168181
```go
169182
func stoneGameIX(stones []int) bool {
170-
check := func(c [3]int) bool {
171-
if c[1] == 0 {
183+
c1 := [3]int{}
184+
for _, x := range stones {
185+
c1[x%3]++
186+
}
187+
c2 := [3]int{c1[0], c1[2], c1[1]}
188+
check := func(cnt [3]int) bool {
189+
if cnt[1] == 0 {
172190
return false
173191
}
174-
c[1]--
175-
turn := 1 + min(c[1], c[2])*2 + c[0]
176-
if c[1] > c[2] {
177-
c[1]--
178-
turn++
192+
cnt[1]--
193+
r := 1 + min(cnt[1], cnt[2])*2 + cnt[0]
194+
if cnt[1] > cnt[2] {
195+
cnt[1]--
196+
r++
179197
}
180-
return turn%2 == 1 && c[1] != c[2]
198+
return r%2 == 1 && cnt[1] != cnt[2]
181199
}
182-
c := [3]int{}
183-
for _, s := range stones {
184-
c[s%3]++
185-
}
186-
return check(c) || check([3]int{c[0], c[2], c[1]})
200+
return check(c1) || check(c2)
201+
}
202+
```
203+
204+
#### TypeScript
205+
206+
```ts
207+
function stoneGameIX(stones: number[]): boolean {
208+
const c1: number[] = Array(3).fill(0);
209+
for (const x of stones) {
210+
++c1[x % 3];
211+
}
212+
const c2: number[] = [c1[0], c1[2], c1[1]];
213+
const check = (cnt: number[]): boolean => {
214+
if (--cnt[1] < 0) {
215+
return false;
216+
}
217+
let r = 1 + Math.min(cnt[1], cnt[2]) * 2 + cnt[0];
218+
if (cnt[1] > cnt[2]) {
219+
--cnt[1];
220+
++r;
221+
}
222+
return r % 2 === 1 && cnt[1] !== cnt[2];
223+
};
224+
return check(c1) || check(c2);
187225
}
188226
```
189227

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

Lines changed: 93 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,19 @@ Alice loses the game because the sum of the removed stones (15) is divisible by
7777

7878
<!-- solution:start -->
7979

80-
### Solution 1
80+
### Solution 1: Greedy + Case Discussion
81+
82+
Since the player's goal is to ensure the total value of the removed stones is not divisible by 3ドル,ドル we only need to consider the remainder of each stone's value when divided by 3ドル$.
83+
84+
We use an array $\textit{cnt}$ of length 3ドル$ to maintain the count of the current remaining stones' values modulo 3ドル,ドル where $\textit{cnt}[0]$ represents the count of stones with a remainder of 0ドル,ドル and $\textit{cnt}[1]$ and $\textit{cnt}[2]$ respectively represent the counts of stones with remainders of 1ドル$ and 2ドル$.
85+
86+
In the first round, Alice cannot remove stones with a remainder of 0ドル,ドル as this would make the total value of the removed stones divisible by 3ドル$. Therefore, Alice can only remove stones with a remainder of 1ドル$ or 2ドル$.
87+
88+
First, let's consider the case where Alice removes a stone with a remainder of 1ドル$. If Alice removes a stone with a remainder of 1ドル,ドル the remainder of the total value of stones 0ドル$ against 3ドル$ will not change, so stones with a value remainder of 0ドル$ can be removed in any round, which we will not consider for now. Thus, Bob can only remove stones with a remainder of 1ドル,ドル followed by Alice removing stones with a remainder of 2ドル,ドル and so on, in the sequence 1,ドル 1, 2, 1, 2, \ldots$. In this scenario, if the final round is odd and there are still remaining stones, then Alice wins; otherwise, Bob wins.
89+
90+
For the case where Alice removes a stone with a remainder of 2ドル$ in the first round, we can draw a similar conclusion.
91+
92+
The time complexity is $O(n),ドル where $n$ is the length of the array $\textit{stones}$. The space complexity is $O(1)$.
8193

8294
<!-- tabs:start -->
8395

@@ -86,47 +98,46 @@ Alice loses the game because the sum of the removed stones (15) is divisible by
8698
```python
8799
class Solution:
88100
def stoneGameIX(self, stones: List[int]) -> bool:
89-
def check(c):
90-
if c[1] == 0:
101+
def check(cnt: List[int]) -> bool:
102+
if cnt[1] == 0:
91103
return False
92-
c[1] -= 1
93-
turn = 1 + min(c[1], c[2]) * 2 + c[0]
94-
if c[1] > c[2]:
95-
turn += 1
96-
c[1] -= 1
97-
return turn % 2 == 1 and c[1] != c[2]
98-
99-
c = [0] * 3
100-
for s in stones:
101-
c[s % 3] += 1
102-
c1 = [c[0], c[2], c[1]]
103-
return check(c) or check(c1)
104+
cnt[1] -= 1
105+
r = 1 + min(cnt[1], cnt[2]) * 2 + cnt[0]
106+
if cnt[1] > cnt[2]:
107+
cnt[1] -= 1
108+
r += 1
109+
return r % 2 == 1 and cnt[1] != cnt[2]
110+
111+
c1 = [0] * 3
112+
for x in stones:
113+
c1[x % 3] += 1
114+
c2 = [c1[0], c1[2], c1[1]]
115+
return check(c1) or check(c2)
104116
```
105117

106118
#### Java
107119

108120
```java
109121
class Solution {
110122
public boolean stoneGameIX(int[] stones) {
111-
int[] c = new int[3];
112-
for (int s : stones) {
113-
++c[s % 3];
123+
int[] c1 = new int[3];
124+
for (int x : stones) {
125+
c1[x % 3]++;
114126
}
115-
int[] t = newint[] {c[0], c[2], c[1]};
116-
return check(c) || check(t);
127+
int[] c2 = {c1[0], c1[2], c1[1]};
128+
return check(c1) || check(c2);
117129
}
118130

119-
private boolean check(int[] c) {
120-
if (c[1] == 0) {
131+
private boolean check(int[] cnt) {
132+
if (--cnt[1] < 0) {
121133
return false;
122134
}
123-
--c[1];
124-
int turn = 1 + Math.min(c[1], c[2]) * 2 + c[0];
125-
if (c[1] > c[2]) {
126-
--c[1];
127-
++turn;
135+
int r = 1 + Math.min(cnt[1], cnt[2]) * 2 + cnt[0];
136+
if (cnt[1] > cnt[2]) {
137+
--cnt[1];
138+
++r;
128139
}
129-
return turn % 2 == 1 && c[1] != c[2];
140+
return r % 2 == 1 && cnt[1] != cnt[2];
130141
}
131142
}
132143
```
@@ -137,21 +148,23 @@ class Solution {
137148
class Solution {
138149
public:
139150
bool stoneGameIX(vector<int>& stones) {
140-
vector<int> c(3);
141-
for (int s : stones) ++c[s % 3];
142-
vector<int> t = {c[0], c[2], c[1]};
143-
return check(c) || check(t);
144-
}
145-
146-
bool check(vector<int>& c) {
147-
if (c[1] == 0) return false;
148-
--c[1];
149-
int turn = 1 + min(c[1], c[2]) * 2 + c[0];
150-
if (c[1] > c[2]) {
151-
--c[1];
152-
++turn;
151+
vector<int> c1(3);
152+
for (int x : stones) {
153+
++c1[x % 3];
153154
}
154-
return turn % 2 == 1 && c[1] != c[2];
155+
vector<int> c2 = {c1[0], c1[2], c1[1]};
156+
auto check = [](auto& cnt) -> bool {
157+
if (--cnt[1] < 0) {
158+
return false;
159+
}
160+
int r = 1 + min(cnt[1], cnt[2]) * 2 + cnt[0];
161+
if (cnt[1] > cnt[2]) {
162+
--cnt[1];
163+
++r;
164+
}
165+
return r % 2 && cnt[1] != cnt[2];
166+
};
167+
return check(c1) || check(c2);
155168
}
156169
};
157170
```
@@ -160,23 +173,48 @@ public:
160173
161174
```go
162175
func stoneGameIX(stones []int) bool {
163-
check := func(c [3]int) bool {
164-
if c[1] == 0 {
176+
c1 := [3]int{}
177+
for _, x := range stones {
178+
c1[x%3]++
179+
}
180+
c2 := [3]int{c1[0], c1[2], c1[1]}
181+
check := func(cnt [3]int) bool {
182+
if cnt[1] == 0 {
165183
return false
166184
}
167-
c[1]--
168-
turn := 1 + min(c[1], c[2])*2 + c[0]
169-
if c[1] > c[2] {
170-
c[1]--
171-
turn++
185+
cnt[1]--
186+
r := 1 + min(cnt[1], cnt[2])*2 + cnt[0]
187+
if cnt[1] > cnt[2] {
188+
cnt[1]--
189+
r++
172190
}
173-
return turn%2 == 1 && c[1] != c[2]
191+
return r%2 == 1 && cnt[1] != cnt[2]
174192
}
175-
c := [3]int{}
176-
for _, s := range stones {
177-
c[s%3]++
178-
}
179-
return check(c) || check([3]int{c[0], c[2], c[1]})
193+
return check(c1) || check(c2)
194+
}
195+
```
196+
197+
#### TypeScript
198+
199+
```ts
200+
function stoneGameIX(stones: number[]): boolean {
201+
const c1: number[] = Array(3).fill(0);
202+
for (const x of stones) {
203+
++c1[x % 3];
204+
}
205+
const c2: number[] = [c1[0], c1[2], c1[1]];
206+
const check = (cnt: number[]): boolean => {
207+
if (--cnt[1] < 0) {
208+
return false;
209+
}
210+
let r = 1 + Math.min(cnt[1], cnt[2]) * 2 + cnt[0];
211+
if (cnt[1] > cnt[2]) {
212+
--cnt[1];
213+
++r;
214+
}
215+
return r % 2 === 1 && cnt[1] !== cnt[2];
216+
};
217+
return check(c1) || check(c2);
180218
}
181219
```
182220

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /