47
47
48
48
** 方法一:记忆化搜索**
49
49
50
- 定义函数 ` dfs(i, j) ` 表示先手面对数组 ` nums[i..j] ` 时,能够获得的最大分数 。
50
+ 我们设计一个函数 $ dfs(i, j)$,表示从第 $i$ 个数到第 $j$ 个数,当前玩家与另一个玩家的得分之差的最大值。那么答案就是 $dfs(0, n - 1) \gt 0$ 。
51
51
52
- 我们先看后手,后手可能面对的情况有两种,分别是 ` nums[i+1..j] ` 和 ` nums[i..j-1] ` ,获得的最大分数分别为 ` dfs(i+1 , j) ` 和 ` dfs(i, j-1) ` 。
52
+ 函数 $ dfs(i, j)$ 的计算方法如下:
53
53
54
- 先手要最大化自己的分数,就要让后手可获得的分数最小,即 ` min(dfs(i+1, j), dfs(i, j-1)) ` 。所以先手能获得的分数为 ` sum(nums[i..j]) - min(dfs(i+1, j), dfs(i, j-1)) ` 。
54
+ - 如果 $i \gt j$,说明当前没有数字了,所以当前玩家没有分数可以拿,差值为 $0$,即 $dfs(i, j) = 0$。
55
+ - 否则,当前玩家有两种选择,如果选择第 $i$ 个数,那么当前玩家与另一个玩家的得分之差为 $nums[ i] - dfs(i + 1, j)$;如果选择第 $j$ 个数,那么当前玩家与另一个玩家的得分之差为 $nums[ j] - dfs(i, j - 1)$。当前玩家会选择两种情况中差值较大的情况,也就是说 $dfs(i, j) = \max(nums[ i] - dfs(i + 1, j), nums[ j] - dfs(i, j - 1))$。
55
56
56
- 记忆化搜索即可 。
57
+ 最后,我们只需要判断 $dfs(0, n - 1) \gt 0$ 即可 。
57
58
58
- 时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为数组 ` nums ` 的长度。
59
+ 为了避免重复计算,我们可以使用记忆化搜索的方法,用一个数组 $f$ 记录所有的 $dfs(i, j)$ 的值,当函数再次被调用到时,我们可以直接从 $f$ 中取出答案而不需要重新计算。
60
+
61
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 是数组的长度。
62
+
63
+ ** 方法二:动态规划**
64
+
65
+ 我们也可以使用动态规划的方法,定义 $f[ i] [ j ] $ 表示当前玩家在 $nums[ i..j] $ 这些数字中能够获得的最大得分的差值。那么最后答案就是 $f[ 0] [ n - 1 ] \gt 0$。
66
+
67
+ 初始时 $f[ i] [ i ] =nums[ i] $,因为只有一个数,所以当前玩家只能拿取这个数,得分差值为 $nums[ i] $。
68
+
69
+ 考虑 $f[ i] [ j ] $,其中 $i \lt j$,有两种情况:
70
+
71
+ - 如果当前玩家拿走了 $nums[ i] $,那么剩下的数字为 $nums[ i + 1..j] $,此时轮到另一个玩家进行游戏,所以 $f[ i] [ j ] = nums[ i] - f[ i + 1] [ j ] $。
72
+ - 如果当前玩家拿走了 $nums[ j] $,那么剩下的数字为 $nums[ i..j - 1] $,此时轮到另一个玩家进行游戏,所以 $f[ i] [ j ] = nums[ j] - f[ i] [ j - 1 ] $。
73
+
74
+ 因此,最终的状态转移方程为 $f[ i] [ j ] = \max(nums[ i] - f[ i + 1] [ j ] , nums[ j] - f[ i] [ j - 1 ] )$。
75
+
76
+ 最后,我们只需要判断 $f[ 0] [ n - 1 ] \gt 0$ 即可。
77
+
78
+ 时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 是数组的长度。
79
+
80
+ 相似题目:
81
+
82
+ - [ 877. 石子游戏] ( /solution/0800-0899/0877.Stone%20Game/README.md )
59
83
60
84
<!-- tabs:start -->
61
85
67
91
class Solution :
68
92
def PredictTheWinner (self , nums : List[int ]) -> bool :
69
93
@cache
70
- def dfs (i , j ) :
94
+ def dfs (i : int , j : int ) -> int :
71
95
if i > j:
72
96
return 0
73
- a = min (dfs(i + 1 , j), dfs(i, j - 1 ))
74
- return s[j + 1 ] - s[i] - a
97
+ return max (nums[i] - dfs(i + 1 , j), nums[j] - dfs(i, j - 1 ))
75
98
76
- s = list (accumulate(nums, initial = 0 ))
77
- return dfs(0 , len (nums) - 1 ) * 2 >= s[- 1 ]
99
+ return dfs(0 , len (nums) - 1 ) >= 0
100
+ ```
101
+
102
+ ``` python
103
+ class Solution :
104
+ def PredictTheWinner (self , nums : List[int ]) -> bool :
105
+ n = len (nums)
106
+ f = [[0 ] * n for _ in range (n)]
107
+ for i, x in enumerate (nums):
108
+ f[i][i] = x
109
+ for i in range (n - 2 , - 1 , - 1 ):
110
+ for j in range (i + 1 , n):
111
+ f[i][j] = max (nums[i] - f[i + 1 ][j], nums[j] - f[i][j - 1 ])
112
+ return f[0 ][n - 1 ] >= 0
78
113
```
79
114
80
115
### ** Java**
@@ -83,52 +118,42 @@ class Solution:
83
118
84
119
``` java
85
120
class Solution {
121
+ private int [] nums;
122
+ private int [][] f;
123
+
86
124
public boolean PredictTheWinner (int [] nums ) {
125
+ this . nums = nums;
87
126
int n = nums. length;
88
- if ((n & 1 ) == 0 ) {
89
- return true ;
127
+ f = new int [n][n];
128
+ return dfs(0 , n - 1 ) >= 0 ;
129
+ }
130
+
131
+ private int dfs (int i , int j ) {
132
+ if (i > j) {
133
+ return 0 ;
90
134
}
91
- int [] f = new int [n];
92
- for (int i = n - 1 ; i >= 0 ; -- i) {
93
- f[i] = nums[i];
94
- for (int j = i + 1 ; j < n; ++ j) {
95
- f[j] = Math . max(nums[i] - f[j], nums[j] - f[j - 1 ]);
96
- }
135
+ if (f[i][j] != 0 ) {
136
+ return f[i][j];
97
137
}
98
- return f[n - 1 ] >= 0 ;
138
+ return f[i][j] = Math . max(nums[i] - dfs(i + 1 , j), nums[j] - dfs(i, j - 1 )) ;
99
139
}
100
140
}
101
141
```
102
142
103
143
``` java
104
144
class Solution {
105
- private int [] s;
106
- private int [][] f;
107
-
108
145
public boolean PredictTheWinner (int [] nums ) {
109
146
int n = nums. length;
110
- s = new int [n + 1 ];
147
+ int [][] f = new int [n][n ];
111
148
for (int i = 0 ; i < n; ++ i) {
112
- s[i + 1 ] = s[i] + nums[i];
113
- }
114
- f = new int [n + 1 ][n + 1 ];
115
- for (var e : f) {
116
- Arrays . fill(e, - 1 );
149
+ f[i][i] = nums[i];
117
150
}
118
- return dfs(0 , n - 1 ) * 2 >= s[n];
119
- }
120
-
121
- private int dfs (int i , int j ) {
122
- if (i > j) {
123
- return 0 ;
124
- }
125
- if (f[i][j] != - 1 ) {
126
- return f[i][j];
151
+ for (int i = n - 2 ; i >= 0 ; -- i) {
152
+ for (int j = i + 1 ; j < n; ++ j) {
153
+ f[i][j] = Math . max(nums[i] - f[i + 1 ][j], nums[j] - f[i][j - 1 ]);
154
+ }
127
155
}
128
- int a = Math . min(dfs(i + 1 , j), dfs(i, j - 1 ));
129
- int res = s[j + 1 ] - s[i] - a;
130
- f[i][j] = res;
131
- return res;
156
+ return f[0 ][n - 1 ] >= 0 ;
132
157
}
133
158
}
134
159
```
@@ -138,26 +163,40 @@ class Solution {
138
163
``` cpp
139
164
class Solution {
140
165
public:
141
- vector<vector<int >> f;
142
- vector<int > s;
166
+ bool PredictTheWinner(vector<int >& nums) {
167
+ int n = nums.size();
168
+ int f[ n] [ n ] ;
169
+ memset(f, 0, sizeof(f));
170
+ function<int(int, int)> dfs = [ &] (int i, int j) -> int {
171
+ if (i > j) {
172
+ return 0;
173
+ }
174
+ if (f[ i] [ j ] ) {
175
+ return f[ i] [ j ] ;
176
+ }
177
+ return f[ i] [ j ] = max(nums[ i] - dfs(i + 1, j), nums[ j] - dfs(i, j - 1));
178
+ };
179
+ return dfs(0, n - 1) >= 0;
180
+ }
181
+ };
182
+ ```
143
183
184
+ ```cpp
185
+ class Solution {
186
+ public:
144
187
bool PredictTheWinner(vector<int>& nums) {
145
188
int n = nums.size();
146
- s.resize(n + 1);
189
+ int f[n][n];
190
+ memset(f, 0, sizeof(f));
147
191
for (int i = 0; i < n; ++i) {
148
- s[i + 1] = s [i] + nums[i];
192
+ f[i] [i] = nums[i];
149
193
}
150
- f.assign(n + 1 , vector<int >(n + 1 , -1 ));
151
- return dfs(0 , n - 1 ) * 2 >= s[n];
152
- }
153
-
154
- int dfs (int i, int j) {
155
- if (i > j) return 0;
156
- if (f[ i] [ j ] != -1) return f[ i] [ j ] ;
157
- int a = min(dfs(i + 1, j), dfs(i, j - 1));
158
- int res = s[ j + 1] - s[ i] - a;
159
- f[ i] [ j ] = res;
160
- return res;
194
+ for (int i = n - 2; ~i; --i) {
195
+ for (int j = i + 1; j < n; ++j) {
196
+ f[i][j] = max(nums[i] - f[i + 1][j], nums[j] - f[i][j - 1]);
197
+ }
198
+ }
199
+ return f[0][n - 1] >= 0;
161
200
}
162
201
};
163
202
```
@@ -166,41 +205,94 @@ public:
166
205
167
206
``` go
168
207
func PredictTheWinner (nums []int ) bool {
169
- n := len(nums)
170
- s := make([]int, n+1)
171
- f := make([][]int, n+1)
172
- for i, v := range nums {
173
- s[i+1] = s[i] + v
174
- }
208
+ n := len (nums)
209
+ f := make ([][]int , n)
175
210
for i := range f {
176
- f[i] = make([]int, n+1)
177
- for j := range f[i] {
178
- f[i][j] = -1
179
- }
211
+ f[i] = make ([]int , n)
180
212
}
181
213
var dfs func (i, j int ) int
182
214
dfs = func (i, j int ) int {
183
215
if i > j {
184
216
return 0
185
217
}
186
- if f[i][j] != -1 {
187
- return f[i][j]
218
+ if f[i][j] == 0 {
219
+ f[i][j] = max (nums[i]- dfs (i+ 1 , j), nums[j]- dfs (i, j- 1 ))
188
220
}
189
- a := min(dfs(i+1, j), dfs(i, j-1))
190
- f[i][j] = s[j+1] - s[i] - a
191
221
return f[i][j]
192
222
}
193
- return dfs(0, n-1)*2 >= s[n]
223
+ return dfs (0 , n-1 ) >= 0
224
+ }
225
+
226
+ func max (a , b int ) int {
227
+ if a > b {
228
+ return a
229
+ }
230
+ return b
231
+ }
232
+ ```
233
+
234
+ ``` go
235
+ func PredictTheWinner (nums []int ) bool {
236
+ n := len (nums)
237
+ f := make ([][]int , n)
238
+ for i , x := range nums {
239
+ f[i] = make ([]int , n)
240
+ f[i][i] = x
241
+ }
242
+ for i := n - 2 ; i >= 0 ; i-- {
243
+ for j := i + 1 ; j < n; j++ {
244
+ f[i][j] = max (nums[i]-f[i+1 ][j], nums[j]-f[i][j-1 ])
245
+ }
246
+ }
247
+ return f[0 ][n-1 ] >= 0
194
248
}
195
249
196
- func min (a, b int) int {
197
- if a < b {
250
+ func max (a , b int ) int {
251
+ if a > b {
198
252
return a
199
253
}
200
254
return b
201
255
}
202
256
```
203
257
258
+ ### ** TypeScript**
259
+
260
+ ``` ts
261
+ function PredictTheWinner(nums : number []): boolean {
262
+ const n = nums .length ;
263
+ const f: number [][] = new Array (n ).fill (0 ).map (() => new Array (n ).fill (0 ));
264
+ const dfs = (i : number , j : number ): number => {
265
+ if (i > j ) {
266
+ return 0 ;
267
+ }
268
+ if (f [i ][j ] === 0 ) {
269
+ f [i ][j ] = Math .max (
270
+ nums [i ] - dfs (i + 1 , j ),
271
+ nums [j ] - dfs (i , j - 1 ),
272
+ );
273
+ }
274
+ return f [i ][j ];
275
+ };
276
+ return dfs (0 , n - 1 ) >= 0 ;
277
+ }
278
+ ```
279
+
280
+ ``` ts
281
+ function PredictTheWinner(nums : number []): boolean {
282
+ const n = nums .length ;
283
+ const f: number [][] = new Array (n ).fill (0 ).map (() => new Array (n ).fill (0 ));
284
+ for (let i = 0 ; i < n ; ++ i ) {
285
+ f [i ][i ] = nums [i ];
286
+ }
287
+ for (let i = n - 2 ; i >= 0 ; -- i ) {
288
+ for (let j = i + 1 ; j < n ; ++ j ) {
289
+ f [i ][j ] = Math .max (nums [i ] - f [i + 1 ][j ], nums [j ] - f [i ][j - 1 ]);
290
+ }
291
+ }
292
+ return f [0 ][n - 1 ] >= 0 ;
293
+ }
294
+ ```
295
+
204
296
### ** ...**
205
297
206
298
```
0 commit comments