Skip to content

Commit 674ac8a

Browse files
committed
feat: add solutions to lc problem: No.1406
No.1406.Stone Game III
1 parent 37f7e41 commit 674ac8a

File tree

7 files changed

+239
-155
lines changed

7 files changed

+239
-155
lines changed

solution/1400-1499/1406.Stone Game III/README.md

Lines changed: 89 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,22 @@
6464

6565
<!-- 这里可写通用的实现逻辑 -->
6666

67-
**方法一:前缀和 + 记忆化搜索**
67+
**方法一:记忆化搜索**
6868

69-
我们先预处理出数组 $stoneValue$ 的前缀和数组 $s$,其中 $s[i]$ 表示 $stoneValue$ 数组前 $i$ 个元素之和
69+
我们设计一个函数 $dfs(i)$,表示当前玩家在 $[i, n)$ 范围内进行游戏时,可以获得的最大得分差值。如果 $dfs(0) \gt 0$,则表示先手玩家 Alice 可以获胜;如果 $dfs(0) \lt 0$,则表示后手玩家 Bob 可以获胜;否则,表示两人打成平局
7070

71-
接下来,我们设计一个函数 $dfs(i)$,表示当前玩家从 $stoneValue$ 数组下标 $i$ 开始拿石子时,能够获得的最大分数。如果当前玩家拿走了 $stoneValue$ 数组下标 $i$ 开始的 $j$ 堆石子,那么下一个玩家能够获得的最大分数为 $dfs(i + j)$,为了使当前玩家获得的分数最大化,我们需要让 $dfs(i + j)$ 最小化,即 $dfs(i) = s[n] - s[i] - min(dfs(i + j))$,其中 $s[n]$ 表示 $stoneValue$ 数组所有元素之和。
71+
函数 $dfs(i)$ 的执行逻辑如下:
7272

73-
最后,玩家 $Alice$ 的分数为 $dfs(0)$,玩家 $Bob$ 的分数为 $s[n] - dfs(0)$,如果 $Alice$ 的分数大于 $Bob$ 的分数,那么 $Alice$ 获胜;如果 $Alice$ 的分数小于 $Bob$ 的分数,那么 $Bob$ 获胜;如果 $Alice$ 的分数等于 $Bob$ 的分数,那么平局。
73+
- 如果 $i \geq n$,说明当前没有石子可以拿了,直接返回 $0$ 即可;
74+
- 否则,我们枚举当前玩家拿走前 $j+1$ 堆石子,其中 $j \in \{0, 1, 2\}$,那么另一个玩家在下一轮可以获得的得分差值为 $dfs(i + j + 1)$,从而当前玩家可以获得的得分差值为 $\sum_{k=i}^{i+j} stoneValue[k] - dfs(i + j + 1)$。我们要使得当前玩家的得分差值最大,因此可以用 $\max$ 函数得到最大得分差值,即:
7475

75-
过程中,我们可以使用记忆化搜索,避免重复计算。
76+
$$
77+
dfs(i) = \max_{j \in \{0, 1, 2\}} \left\{\sum_{k=i}^{i+j} stoneValue[k] - dfs(i + j + 1)\right\}
78+
$$
7679

77-
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $stoneValue$ 的长度。
80+
为了防止重复计算,我们可以使用记忆化搜索。
81+
82+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是石子的堆数。
7883

7984
<!-- tabs:start -->
8085

@@ -87,17 +92,21 @@ class Solution:
8792
def stoneGameIII(self, stoneValue: List[int]) -> str:
8893
@cache
8994
def dfs(i: int) -> int:
90-
if i >= len(stoneValue):
95+
if i >= n:
9196
return 0
92-
t = min(dfs(i + j) for j in range(1, 4))
93-
return s[-1] - s[i] - t
94-
95-
s = list(accumulate(stoneValue, initial=0))
96-
a = dfs(0)
97-
b = s[-1] - a
98-
if a == b:
97+
ans, s = -inf, 0
98+
for j in range(3):
99+
if i + j >= n:
100+
break
101+
s += stoneValue[i + j]
102+
ans = max(ans, s - dfs(i + j + 1))
103+
return ans
104+
105+
n = len(stoneValue)
106+
ans = dfs(0)
107+
if ans == 0:
99108
return 'Tie'
100-
return 'Alice' if a > b else 'Bob'
109+
return 'Alice' if ans > 0 else 'Bob'
101110
```
102111

103112
### **Java**
@@ -106,20 +115,19 @@ class Solution:
106115

107116
```java
108117
class Solution {
109-
private int n;
110-
private int[] s;
118+
private int[] stoneValue;
111119
private Integer[] f;
120+
private int n;
112121

113122
public String stoneGameIII(int[] stoneValue) {
114123
n = stoneValue.length;
115-
s = new int[n + 1];
116124
f = new Integer[n];
117-
for (int i = 1; i <= n; ++i) {
118-
s[i] = s[i - 1] + stoneValue[i - 1];
125+
this.stoneValue = stoneValue;
126+
int ans = dfs(0);
127+
if (ans == 0) {
128+
return "Tie";
119129
}
120-
int a = dfs(0);
121-
int b = s[n] - a;
122-
return a == b ? "Tie" : a > b ? "Alice" : "Bob";
130+
return ans > 0 ? "Alice" : "Bob";
123131
}
124132

125133
private int dfs(int i) {
@@ -129,12 +137,13 @@ class Solution {
129137
if (f[i] != null) {
130138
return f[i];
131139
}
132-
int t = 1 << 30;
133-
for (int j = 1; j < 4; ++j) {
134-
t = Math.min(t, dfs(i + j));
140+
int ans = -(1 << 30);
141+
int s = 0;
142+
for (int j = 0; j < 3 && i + j < n; ++j) {
143+
s += stoneValue[i + j];
144+
ans = Math.max(ans, s - dfs(i + j + 1));
135145
}
136-
f[i] = s[n] - s[i] - t;
137-
return f[i];
146+
return f[i] = ans;
138147
}
139148
}
140149
```
@@ -146,11 +155,6 @@ class Solution {
146155
public:
147156
string stoneGameIII(vector<int>& stoneValue) {
148157
int n = stoneValue.size();
149-
int s[n + 1];
150-
s[0] = 0;
151-
for (int i = 1; i <= n; ++i) {
152-
s[i] = s[i - 1] + stoneValue[i - 1];
153-
}
154158
int f[n];
155159
memset(f, 0x3f, sizeof(f));
156160
function<int(int)> dfs = [&](int i) -> int {
@@ -160,15 +164,18 @@ public:
160164
if (f[i] != 0x3f3f3f3f) {
161165
return f[i];
162166
}
163-
int t = 1 << 30;
164-
for (int j = 1; j < 4; ++j) {
165-
t = min(t, dfs(i + j));
167+
int ans = -(1 << 30), s = 0;
168+
for (int j = 0; j < 3 && i + j < n; ++j) {
169+
s += stoneValue[i + j];
170+
ans = max(ans, s - dfs(i + j + 1));
166171
}
167-
return f[i] = s[n] - s[i] - t;
172+
return f[i] = ans;
168173
};
169-
int a = dfs(0);
170-
int b = s[n] - a;
171-
return a == b ? "Tie" : (a > b ? "Alice" : "Bob");
174+
int ans = dfs(0);
175+
if (ans == 0) {
176+
return "Tie";
177+
}
178+
return ans > 0 ? "Alice" : "Bob";
172179
}
173180
};
174181
```
@@ -178,12 +185,8 @@ public:
178185
```go
179186
func stoneGameIII(stoneValue []int) string {
180187
n := len(stoneValue)
181-
s := make([]int, n+1)
182-
for i, x := range stoneValue {
183-
s[i+1] = s[i] + x
184-
}
185-
const inf = 1 << 30
186188
f := make([]int, n)
189+
const inf = 1 << 30
187190
for i := range f {
188191
f[i] = inf
189192
}
@@ -195,32 +198,62 @@ func stoneGameIII(stoneValue []int) string {
195198
if f[i] != inf {
196199
return f[i]
197200
}
198-
t := inf
199-
for j := 1; j <= 3; j++ {
200-
t = min(t, dfs(i+j))
201+
ans, s := -(1 << 30), 0
202+
for j := 0; j < 3 && i+j < n; j++ {
203+
s += stoneValue[i+j]
204+
ans = max(ans, s-dfs(i+j+1))
201205
}
202-
f[i] = s[n] - s[i] - t
203-
return f[i]
206+
f[i] = ans
207+
return ans
204208
}
205-
a := dfs(0)
206-
b := s[n] - a
207-
if a == b {
209+
ans := dfs(0)
210+
if ans == 0 {
208211
return "Tie"
209212
}
210-
if a > b {
213+
if ans > 0 {
211214
return "Alice"
212215
}
213216
return "Bob"
214217
}
215218
216-
func min(a, b int) int {
217-
if a < b {
219+
func max(a, b int) int {
220+
if a > b {
218221
return a
219222
}
220223
return b
221224
}
222225
```
223226

227+
### **TypeScript**
228+
229+
```ts
230+
function stoneGameIII(stoneValue: number[]): string {
231+
const n = stoneValue.length;
232+
const inf = 1 << 30;
233+
const f: number[] = new Array(n).fill(inf);
234+
const dfs = (i: number): number => {
235+
if (i >= n) {
236+
return 0;
237+
}
238+
if (f[i] !== inf) {
239+
return f[i];
240+
}
241+
let ans = -inf;
242+
let s = 0;
243+
for (let j = 0; j < 3 && i + j < n; ++j) {
244+
s += stoneValue[i + j];
245+
ans = Math.max(ans, s - dfs(i + j + 1));
246+
}
247+
return (f[i] = ans);
248+
};
249+
const ans = dfs(0);
250+
if (ans === 0) {
251+
return 'Tie';
252+
}
253+
return ans > 0 ? 'Alice' : 'Bob';
254+
}
255+
```
256+
224257
### **...**
225258

226259
```

0 commit comments

Comments
 (0)