Skip to content

Commit 072ca8e

Browse files
committed
feat: add solutions to lc problem: No.1140
No.1140.Stone Game II
1 parent 5a65b3f commit 072ca8e

File tree

6 files changed

+318
-26
lines changed

6 files changed

+318
-26
lines changed

solution/1100-1199/1140.Stone Game II/README.md

+123-1
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,144 @@
4646

4747
<!-- 这里可写通用的实现逻辑 -->
4848

49+
**方法一:前缀和 + 记忆化搜索**
50+
51+
我们先预处理出前缀和数组 $s$,其中 $s[i]$ 表示数组 `piles` 的前 $i$ 个元素的和。
52+
53+
然后我们设计一个函数 $dfs(i, m)$,表示当前轮到的人可以从数组 `piles` 的下标 $i$ 开始拿,且当前的 $M$ 为 $m$ 时,当前轮到的人能够拿到的最大石子数。那么答案就是 $dfs(0, 1)$。
54+
55+
函数 $dfs(i, m)$ 的计算过程如下:
56+
57+
- 如果当前轮到的人可以拿走剩下的所有石子,那么当前轮到的人就可以拿走剩下的所有石子,因此当前轮到的人能够拿到的最大石子数为 $s[n] - s[i]$,其中 $n$ 为数组 `piles` 的长度。
58+
- 否则,当前轮到的人可以拿走剩下的前 $x$ 堆的所有石子,其中 $1 \leq x \leq 2m$,那么当前轮到的人能够拿到的最大石子数为 $s[n] - s[i] - dfs(i + x, max(m, x))$。我们需要遍历所有的 $x$,取其中的最大值。
59+
60+
最后,我们返回 $dfs(0, 1)$ 即可。
61+
62+
为了避免重复计算,我们可以使用记忆化搜索。
63+
64+
时间复杂度为 $O(n^2)$,空间复杂度为 $O(n^2)$。其中 $n$ 为数组 `piles` 的长度。
65+
4966
<!-- tabs:start -->
5067

5168
### **Python3**
5269

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

5572
```python
56-
73+
class Solution:
74+
def stoneGameII(self, piles: List[int]) -> int:
75+
@cache
76+
def dfs(i, m):
77+
if m * 2 >= n - i:
78+
return s[-1] - s[i]
79+
res = 0
80+
for x in range(1, m << 1 | 1):
81+
t = s[-1] - s[i] - dfs(i + x, max(m, x))
82+
res = max(res, t)
83+
return res
84+
85+
s = list(accumulate(piles, initial=0))
86+
n = len(piles)
87+
return dfs(0, 1)
5788
```
5889

5990
### **Java**
6091

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

6394
```java
95+
class Solution {
96+
private int[] s;
97+
private Integer[][] f;
98+
private int n;
99+
100+
public int stoneGameII(int[] piles) {
101+
n = piles.length;
102+
s = new int[n + 1];
103+
f = new Integer[n][n + 1];
104+
for (int i = 0; i < n; ++i) {
105+
s[i + 1] = s[i] + piles[i];
106+
}
107+
return dfs(0, 1);
108+
}
109+
110+
private int dfs(int i, int m) {
111+
if (m * 2 >= n - i) {
112+
return s[n] - s[i];
113+
}
114+
if (f[i][m] != null) {
115+
return f[i][m];
116+
}
117+
f[i][m] = 0;
118+
for (int x = 1; x <= m * 2; ++x) {
119+
int t = s[n] - s[i] - dfs(i + x, Math.max(m, x));
120+
f[i][m] = Math.max(f[i][m], t);
121+
}
122+
return f[i][m];
123+
}
124+
}
125+
```
126+
127+
### **C++**
128+
129+
```cpp
130+
class Solution {
131+
public:
132+
int stoneGameII(vector<int>& piles) {
133+
int n = piles.size();
134+
int s[n + 1];
135+
s[0] = 0;
136+
for (int i = 0; i < n; ++i) s[i + 1] = s[i] + piles[i];
137+
int f[n][n + 1];
138+
memset(f, 0, sizeof f);
139+
function<int(int, int)> dfs = [&](int i, int m) -> int {
140+
if (m * 2 >= n - i) return s[n] - s[i];
141+
if (f[i][m]) return f[i][m];
142+
for (int x = 1; x <= m << 1; ++x) {
143+
int t = s[n] - s[i] - dfs(i + x, max(x, m));
144+
f[i][m] = max(f[i][m], t);
145+
}
146+
return f[i][m];
147+
};
148+
return dfs(0, 1);
149+
}
150+
};
151+
```
64152
153+
### **Go**
154+
155+
```go
156+
func stoneGameII(piles []int) int {
157+
n := len(piles)
158+
s := make([]int, n+1)
159+
f := make([][]int, n+1)
160+
for i, v := range piles {
161+
s[i+1] = s[i] + v
162+
f[i] = make([]int, n+1)
163+
}
164+
var dfs func(i, m int) int
165+
dfs = func(i, m int) int {
166+
if m*2 >= n-i {
167+
return s[n] - s[i]
168+
}
169+
if f[i][m] > 0 {
170+
return f[i][m]
171+
}
172+
for x := 1; x <= m<<1; x++ {
173+
t := s[n] - s[i] - dfs(i+x, max(m, x))
174+
f[i][m] = max(f[i][m], t)
175+
}
176+
return f[i][m]
177+
}
178+
return dfs(0, 1)
179+
}
180+
181+
func max(a, b int) int {
182+
if a > b {
183+
return a
184+
}
185+
return b
186+
}
65187
```
66188

67189
### **...**

solution/1100-1199/1140.Stone Game II/README_EN.md

+106-1
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,118 @@
4545
### **Python3**
4646

4747
```python
48-
48+
class Solution:
49+
def stoneGameII(self, piles: List[int]) -> int:
50+
@cache
51+
def dfs(i, m):
52+
if m * 2 >= n - i:
53+
return s[-1] - s[i]
54+
res = 0
55+
for x in range(1, m << 1 | 1):
56+
t = s[-1] - s[i] - dfs(i + x, max(m, x))
57+
res = max(res, t)
58+
return res
59+
60+
s = list(accumulate(piles, initial=0))
61+
n = len(piles)
62+
return dfs(0, 1)
4963
```
5064

5165
### **Java**
5266

5367
```java
68+
class Solution {
69+
private int[] s;
70+
private Integer[][] f;
71+
private int n;
72+
73+
public int stoneGameII(int[] piles) {
74+
n = piles.length;
75+
s = new int[n + 1];
76+
f = new Integer[n][n + 1];
77+
for (int i = 0; i < n; ++i) {
78+
s[i + 1] = s[i] + piles[i];
79+
}
80+
return dfs(0, 1);
81+
}
82+
83+
private int dfs(int i, int m) {
84+
if (m * 2 >= n - i) {
85+
return s[n] - s[i];
86+
}
87+
if (f[i][m] != null) {
88+
return f[i][m];
89+
}
90+
f[i][m] = 0;
91+
for (int x = 1; x <= m * 2; ++x) {
92+
int t = s[n] - s[i] - dfs(i + x, Math.max(m, x));
93+
f[i][m] = Math.max(f[i][m], t);
94+
}
95+
return f[i][m];
96+
}
97+
}
98+
```
99+
100+
### **C++**
101+
102+
```cpp
103+
class Solution {
104+
public:
105+
int stoneGameII(vector<int>& piles) {
106+
int n = piles.size();
107+
int s[n + 1];
108+
s[0] = 0;
109+
for (int i = 0; i < n; ++i) s[i + 1] = s[i] + piles[i];
110+
int f[n][n + 1];
111+
memset(f, 0, sizeof f);
112+
function<int(int, int)> dfs = [&](int i, int m) -> int {
113+
if (m * 2 >= n - i) return s[n] - s[i];
114+
if (f[i][m]) return f[i][m];
115+
for (int x = 1; x <= m << 1; ++x) {
116+
int t = s[n] - s[i] - dfs(i + x, max(x, m));
117+
f[i][m] = max(f[i][m], t);
118+
}
119+
return f[i][m];
120+
};
121+
return dfs(0, 1);
122+
}
123+
};
124+
```
54125
126+
### **Go**
127+
128+
```go
129+
func stoneGameII(piles []int) int {
130+
n := len(piles)
131+
s := make([]int, n+1)
132+
f := make([][]int, n+1)
133+
for i, v := range piles {
134+
s[i+1] = s[i] + v
135+
f[i] = make([]int, n+1)
136+
}
137+
var dfs func(i, m int) int
138+
dfs = func(i, m int) int {
139+
if m*2 >= n-i {
140+
return s[n] - s[i]
141+
}
142+
if f[i][m] > 0 {
143+
return f[i][m]
144+
}
145+
for x := 1; x <= m<<1; x++ {
146+
t := s[n] - s[i] - dfs(i+x, max(m, x))
147+
f[i][m] = max(f[i][m], t)
148+
}
149+
return f[i][m]
150+
}
151+
return dfs(0, 1)
152+
}
153+
154+
func max(a, b int) int {
155+
if a > b {
156+
return a
157+
}
158+
return b
159+
}
55160
```
56161

57162
### **...**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class Solution {
2+
public:
3+
int stoneGameII(vector<int>& piles) {
4+
int n = piles.size();
5+
int s[n + 1];
6+
s[0] = 0;
7+
for (int i = 0; i < n; ++i) s[i + 1] = s[i] + piles[i];
8+
int f[n][n + 1];
9+
memset(f, 0, sizeof f);
10+
function<int(int, int)> dfs = [&](int i, int m) -> int {
11+
if (m * 2 >= n - i) return s[n] - s[i];
12+
if (f[i][m]) return f[i][m];
13+
for (int x = 1; x <= m << 1; ++x) {
14+
int t = s[n] - s[i] - dfs(i + x, max(x, m));
15+
f[i][m] = max(f[i][m], t);
16+
}
17+
return f[i][m];
18+
};
19+
return dfs(0, 1);
20+
}
21+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
func stoneGameII(piles []int) int {
2+
n := len(piles)
3+
s := make([]int, n+1)
4+
f := make([][]int, n+1)
5+
for i, v := range piles {
6+
s[i+1] = s[i] + v
7+
f[i] = make([]int, n+1)
8+
}
9+
var dfs func(i, m int) int
10+
dfs = func(i, m int) int {
11+
if m*2 >= n-i {
12+
return s[n] - s[i]
13+
}
14+
if f[i][m] > 0 {
15+
return f[i][m]
16+
}
17+
for x := 1; x <= m<<1; x++ {
18+
t := s[n] - s[i] - dfs(i+x, max(m, x))
19+
f[i][m] = max(f[i][m], t)
20+
}
21+
return f[i][m]
22+
}
23+
return dfs(0, 1)
24+
}
25+
26+
func max(a, b int) int {
27+
if a > b {
28+
return a
29+
}
30+
return b
31+
}
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,30 @@
11
class Solution {
2+
private int[] s;
3+
private Integer[][] f;
4+
private int n;
5+
26
public int stoneGameII(int[] piles) {
3-
Map<Integer, Integer> map = new HashMap<>();
4-
int total = Arrays.stream(piles).sum();
5-
return (total + dfs(0, 1, piles, map)) >> 1;
7+
n = piles.length;
8+
s = new int[n + 1];
9+
f = new Integer[n][n + 1];
10+
for (int i = 0; i < n; ++i) {
11+
s[i + 1] = s[i] + piles[i];
12+
}
13+
return dfs(0, 1);
614
}
715

8-
private int dfs(int s, int M, int[] piles, Map<Integer, Integer> map) {
9-
if (s >= piles.length) {
10-
return 0;
11-
}
12-
int key = s << 8 | M;
13-
if (map.containsKey(key)) {
14-
return map.get(key);
16+
private int dfs(int i, int m) {
17+
if (m * 2 >= n - i) {
18+
return s[n] - s[i];
1519
}
16-
if (s + 2 * M >= piles.length) {
17-
int res = 0;
18-
for (int i = s; i < piles.length; ++i) {
19-
res += piles[i];
20-
}
21-
return res;
20+
if (f[i][m] != null) {
21+
return f[i][m];
2222
}
23-
int best = Integer.MIN_VALUE;
24-
int cur = 0;
25-
for (int x = 1; x <= 2 * M && s + x - 1 < piles.length; ++x) {
26-
cur += piles[s + x - 1];
27-
best = Math.max(best, cur - dfs(s + x, Math.max(x, M), piles, map));
23+
f[i][m] = 0;
24+
for (int x = 1; x <= m * 2; ++x) {
25+
int t = s[n] - s[i] - dfs(i + x, Math.max(m, x));
26+
f[i][m] = Math.max(f[i][m], t);
2827
}
29-
map.put(key, best);
30-
return best;
28+
return f[i][m];
3129
}
32-
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Solution:
2+
def stoneGameII(self, piles: List[int]) -> int:
3+
@cache
4+
def dfs(i, m):
5+
if m * 2 >= n - i:
6+
return s[-1] - s[i]
7+
res = 0
8+
for x in range(1, m << 1 | 1):
9+
t = s[-1] - s[i] - dfs(i + x, max(m, x))
10+
res = max(res, t)
11+
return res
12+
13+
s = list(accumulate(piles, initial=0))
14+
n = len(piles)
15+
return dfs(0, 1)

0 commit comments

Comments
 (0)