64
64
65
65
<!-- 这里可写通用的实现逻辑 -->
66
66
67
- ** 方法一:前缀和 + 记忆化搜索**
67
+ ** 方法一:记忆化搜索**
68
68
69
- 我们先预处理出数组 $stoneValue$ 的前缀和数组 $s$,其中 $s [ i ] $ 表示 $stoneValue$ 数组前 $i$ 个元素之和 。
69
+ 我们设计一个函数 $dfs(i)$,表示当前玩家在 $ [ i, n)$ 范围内进行游戏时,可以获得的最大得分差值。如果 $dfs(0) \gt 0$,则表示先手玩家 Alice 可以获胜;如果 $dfs(0) \lt 0$,则表示后手玩家 Bob 可以获胜;否则,表示两人打成平局 。
70
70
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)$ 的执行逻辑如下:
72
72
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$ 函数得到最大得分差值,即:
74
75
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
+ $$
76
79
77
- 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $stoneValue$ 的长度。
80
+ 为了防止重复计算,我们可以使用记忆化搜索。
81
+
82
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是石子的堆数。
78
83
79
84
<!-- tabs:start -->
80
85
@@ -87,17 +92,21 @@ class Solution:
87
92
def stoneGameIII (self , stoneValue : List[int ]) -> str :
88
93
@cache
89
94
def dfs (i : int ) -> int :
90
- if i >= len (stoneValue) :
95
+ if i >= n :
91
96
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 :
99
108
return ' Tie'
100
- return ' Alice' if a > b else ' Bob'
109
+ return ' Alice' if ans > 0 else ' Bob'
101
110
```
102
111
103
112
### ** Java**
@@ -106,20 +115,19 @@ class Solution:
106
115
107
116
``` java
108
117
class Solution {
109
- private int n;
110
- private int [] s;
118
+ private int [] stoneValue;
111
119
private Integer [] f;
120
+ private int n;
112
121
113
122
public String stoneGameIII (int [] stoneValue ) {
114
123
n = stoneValue. length;
115
- s = new int [n + 1 ];
116
124
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" ;
119
129
}
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" ;
123
131
}
124
132
125
133
private int dfs (int i ) {
@@ -129,12 +137,13 @@ class Solution {
129
137
if (f[i] != null ) {
130
138
return f[i];
131
139
}
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 ));
135
145
}
136
- f[i] = s[n] - s[i] - t;
137
- return f[i];
146
+ return f[i] = ans;
138
147
}
139
148
}
140
149
```
@@ -146,11 +155,6 @@ class Solution {
146
155
public:
147
156
string stoneGameIII(vector<int >& stoneValue) {
148
157
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
- }
154
158
int f[ n] ;
155
159
memset(f, 0x3f, sizeof(f));
156
160
function<int(int)> dfs = [ &] (int i) -> int {
@@ -160,15 +164,18 @@ public:
160
164
if (f[ i] != 0x3f3f3f3f) {
161
165
return f[ i] ;
162
166
}
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));
166
171
}
167
- return f[ i] = s [ n ] - s [ i ] - t ;
172
+ return f[ i] = ans ;
168
173
};
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";
172
179
}
173
180
};
174
181
```
@@ -178,12 +185,8 @@ public:
178
185
```go
179
186
func stoneGameIII(stoneValue []int) string {
180
187
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
186
188
f := make([]int, n)
189
+ const inf = 1 << 30
187
190
for i := range f {
188
191
f[i] = inf
189
192
}
@@ -195,32 +198,62 @@ func stoneGameIII(stoneValue []int) string {
195
198
if f[i] != inf {
196
199
return f[i]
197
200
}
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))
201
205
}
202
- f[i] = s[n] - s[i] - t
203
- return f[i]
206
+ f[i] = ans
207
+ return ans
204
208
}
205
- a := dfs(0)
206
- b := s[n] - a
207
- if a == b {
209
+ ans := dfs(0)
210
+ if ans == 0 {
208
211
return "Tie"
209
212
}
210
- if a > b {
213
+ if ans > 0 {
211
214
return "Alice"
212
215
}
213
216
return "Bob"
214
217
}
215
218
216
- func min (a, b int) int {
217
- if a < b {
219
+ func max (a, b int) int {
220
+ if a > b {
218
221
return a
219
222
}
220
223
return b
221
224
}
222
225
```
223
226
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
+
224
257
### ** ...**
225
258
226
259
```
0 commit comments