Skip to content

Commit ebe805a

Browse files
authoredFeb 2, 2024
feat: add solutions to lc problem: No.1690 (#2298)
No.1690.Stone Game VII
1 parent 53fea67 commit ebe805a

File tree

9 files changed

+380
-3
lines changed

9 files changed

+380
-3
lines changed
 

‎solution/1600-1699/1690.Stone Game VII/README.md

+138-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
class Solution:
7070
def stoneGameVII(self, stones: List[int]) -> int:
7171
@cache
72-
def dfs(i, j):
72+
def dfs(i: int, j: int) -> int:
7373
if i > j:
7474
return 0
7575
a = s[j + 1] - s[i + 1] - dfs(i + 1, j)
@@ -165,6 +165,143 @@ func stoneGameVII(stones []int) int {
165165
}
166166
```
167167

168+
```ts
169+
function stoneGameVII(stones: number[]): number {
170+
const n = stones.length;
171+
const s: number[] = Array(n + 1).fill(0);
172+
for (let i = 0; i < n; ++i) {
173+
s[i + 1] = s[i] + stones[i];
174+
}
175+
const f: number[][] = Array.from({ length: n }, () => Array(n).fill(0));
176+
const dfs = (i: number, j: number): number => {
177+
if (i > j) {
178+
return 0;
179+
}
180+
if (f[i][j]) {
181+
return f[i][j];
182+
}
183+
const a = s[j + 1] - s[i + 1] - dfs(i + 1, j);
184+
const b = s[j] - s[i] - dfs(i, j - 1);
185+
return (f[i][j] = Math.max(a, b));
186+
};
187+
return dfs(0, n - 1);
188+
}
189+
```
190+
168191
<!-- tabs:end -->
169192

193+
### 方法二:动态规划
194+
195+
我们可以将方法一中的记忆化搜索转换为动态规划,定义 $f[i][j]$ 表示当剩下的石子为 $stones[i], stones[i + 1], \dots, stones[j]$ 时,先手与后手的得分差值。那么答案即为 $f[0][n - 1]$。
196+
197+
状态转移方程如下:
198+
199+
$$
200+
f[i][j] = \max(s[j + 1] - s[i + 1] - f[i + 1][j], s[j] - s[i] - f[i][j - 1])
201+
$$
202+
203+
在计算 $f[i][j]$ 时,我们需要保证 $f[i + 1][j]$ 和 $f[i][j - 1]$ 已经被计算出来,因此我们需要按照从大到小的顺序枚举 $i$,从小到大的顺序枚举 $j$。
204+
205+
最后,答案即为 $f[0][n - 1]$。
206+
207+
时间复杂度 $O(n^2)$,空间复杂度 $O(n^2)$。其中 $n$ 为石子的数量。
208+
209+
<!-- tabs:start -->
210+
211+
```python
212+
class Solution:
213+
def stoneGameVII(self, stones: List[int]) -> int:
214+
s = list(accumulate(stones, initial=0))
215+
n = len(stones)
216+
f = [[0] * n for _ in range(n)]
217+
for i in range(n - 2, -1, -1):
218+
for j in range(i + 1, n):
219+
a = s[j + 1] - s[i + 1] - f[i + 1][j]
220+
b = s[j] - s[i] - f[i][j - 1]
221+
f[i][j] = max(a, b)
222+
return f[0][-1]
223+
```
224+
225+
```java
226+
class Solution {
227+
public int stoneGameVII(int[] stones) {
228+
int n = stones.length;
229+
int[] s = new int[n + 1];
230+
for (int i = 0; i < n; ++i) {
231+
s[i + 1] = s[i] + stones[i];
232+
}
233+
int[][] f = new int[n][n];
234+
for (int i = n - 2; i >= 0; --i) {
235+
for (int j = i + 1; j < n; ++j) {
236+
int a = s[j + 1] - s[i + 1] - f[i + 1][j];
237+
int b = s[j] - s[i] - f[i][j - 1];
238+
f[i][j] = Math.max(a, b);
239+
}
240+
}
241+
return f[0][n - 1];
242+
}
243+
}
244+
```
245+
246+
```cpp
247+
class Solution {
248+
public:
249+
int stoneGameVII(vector<int>& stones) {
250+
int n = stones.size();
251+
int s[n + 1];
252+
memset(s, 0, sizeof(s));
253+
for (int i = 0; i < n; ++i) {
254+
s[i + 1] = s[i] + stones[i];
255+
}
256+
int f[n][n];
257+
memset(f, 0, sizeof(f));
258+
for (int i = n - 2; i >= 0; --i) {
259+
for (int j = i + 1; j < n; ++j) {
260+
int a = s[j + 1] - s[i + 1] - f[i + 1][j];
261+
int b = s[j] - s[i] - f[i][j - 1];
262+
f[i][j] = max(a, b);
263+
}
264+
}
265+
return f[0][n - 1];
266+
}
267+
};
268+
```
269+
270+
```go
271+
func stoneGameVII(stones []int) int {
272+
n := len(stones)
273+
s := make([]int, n+1)
274+
for i, x := range stones {
275+
s[i+1] = s[i] + x
276+
}
277+
f := make([][]int, n)
278+
for i := range f {
279+
f[i] = make([]int, n)
280+
}
281+
for i := n - 2; i >= 0; i-- {
282+
for j := i + 1; j < n; j++ {
283+
f[i][j] = max(s[j+1]-s[i+1]-f[i+1][j], s[j]-s[i]-f[i][j-1])
284+
}
285+
}
286+
return f[0][n-1]
287+
}
288+
```
289+
290+
```ts
291+
function stoneGameVII(stones: number[]): number {
292+
const n = stones.length;
293+
const s: number[] = Array(n + 1).fill(0);
294+
for (let i = 0; i < n; ++i) {
295+
s[i + 1] = s[i] + stones[i];
296+
}
297+
const f: number[][] = Array.from({ length: n }, () => Array(n).fill(0));
298+
for (let i = n - 2; ~i; --i) {
299+
for (let j = i + 1; j < n; ++j) {
300+
f[i][j] = Math.max(s[j + 1] - s[i + 1] - f[i + 1][j], s[j] - s[i] - f[i][j - 1]);
301+
}
302+
}
303+
return f[0][n - 1];
304+
}
305+
```
306+
170307
<!-- end -->

‎solution/1600-1699/1690.Stone Game VII/README_EN.md

+140-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ The time complexity is $O(n^2)$, and the space complexity is $O(n^2)$. Here, $n$
6565
class Solution:
6666
def stoneGameVII(self, stones: List[int]) -> int:
6767
@cache
68-
def dfs(i, j):
68+
def dfs(i: int, j: int) -> int:
6969
if i > j:
7070
return 0
7171
a = s[j + 1] - s[i + 1] - dfs(i + 1, j)
@@ -161,6 +161,145 @@ func stoneGameVII(stones []int) int {
161161
}
162162
```
163163

164+
```ts
165+
function stoneGameVII(stones: number[]): number {
166+
const n = stones.length;
167+
const s: number[] = Array(n + 1).fill(0);
168+
for (let i = 0; i < n; ++i) {
169+
s[i + 1] = s[i] + stones[i];
170+
}
171+
const f: number[][] = Array.from({ length: n }, () => Array(n).fill(0));
172+
const dfs = (i: number, j: number): number => {
173+
if (i > j) {
174+
return 0;
175+
}
176+
if (f[i][j]) {
177+
return f[i][j];
178+
}
179+
const a = s[j + 1] - s[i + 1] - dfs(i + 1, j);
180+
const b = s[j] - s[i] - dfs(i, j - 1);
181+
return (f[i][j] = Math.max(a, b));
182+
};
183+
return dfs(0, n - 1);
184+
}
185+
```
186+
187+
<!-- tabs:end -->
188+
189+
### Solution 2: Dynamic Programming
190+
191+
We can convert the memoization search in Solution 1 into dynamic programming. We define $f[i][j]$ as the score difference between the first and second players when the remaining stones are $stones[i], stones[i + 1], \dots, stones[j]$. Therefore, the answer is $f[0][n - 1]$.
192+
193+
The state transition equation is as follows:
194+
195+
$$
196+
f[i][j] = \max(s[j + 1] - s[i + 1] - f[i + 1][j], s[j] - s[i] - f[i][j - 1])
197+
$$
198+
199+
When calculating $f[i][j]$, we need to ensure that $f[i + 1][j]$ and $f[i][j - 1]$ have been calculated. Therefore, we need to enumerate $i$ in descending order and $j$ in ascending order.
200+
201+
Finally, the answer is $f[0][n - 1]$.
202+
203+
The time complexity is $O(n^2)$, and the space complexity is $O(n^2)$. Here, $n$ is the number of stones.
204+
205+
<!-- tabs:start -->
206+
207+
```python
208+
class Solution:
209+
def stoneGameVII(self, stones: List[int]) -> int:
210+
s = list(accumulate(stones, initial=0))
211+
n = len(stones)
212+
f = [[0] * n for _ in range(n)]
213+
for i in range(n - 2, -1, -1):
214+
for j in range(i + 1, n):
215+
a = s[j + 1] - s[i + 1] - f[i + 1][j]
216+
b = s[j] - s[i] - f[i][j - 1]
217+
f[i][j] = max(a, b)
218+
return f[0][-1]
219+
```
220+
221+
```java
222+
class Solution {
223+
public int stoneGameVII(int[] stones) {
224+
int n = stones.length;
225+
int[] s = new int[n + 1];
226+
for (int i = 0; i < n; ++i) {
227+
s[i + 1] = s[i] + stones[i];
228+
}
229+
int[][] f = new int[n][n];
230+
for (int i = n - 2; i >= 0; --i) {
231+
for (int j = i + 1; j < n; ++j) {
232+
int a = s[j + 1] - s[i + 1] - f[i + 1][j];
233+
int b = s[j] - s[i] - f[i][j - 1];
234+
f[i][j] = Math.max(a, b);
235+
}
236+
}
237+
return f[0][n - 1];
238+
}
239+
}
240+
```
241+
242+
```cpp
243+
class Solution {
244+
public:
245+
int stoneGameVII(vector<int>& stones) {
246+
int n = stones.size();
247+
int s[n + 1];
248+
memset(s, 0, sizeof(s));
249+
for (int i = 0; i < n; ++i) {
250+
s[i + 1] = s[i] + stones[i];
251+
}
252+
int f[n][n];
253+
memset(f, 0, sizeof(f));
254+
for (int i = n - 2; i >= 0; --i) {
255+
for (int j = i + 1; j < n; ++j) {
256+
int a = s[j + 1] - s[i + 1] - f[i + 1][j];
257+
int b = s[j] - s[i] - f[i][j - 1];
258+
f[i][j] = max(a, b);
259+
}
260+
}
261+
return f[0][n - 1];
262+
}
263+
};
264+
```
265+
266+
```go
267+
func stoneGameVII(stones []int) int {
268+
n := len(stones)
269+
s := make([]int, n+1)
270+
for i, x := range stones {
271+
s[i+1] = s[i] + x
272+
}
273+
f := make([][]int, n)
274+
for i := range f {
275+
f[i] = make([]int, n)
276+
}
277+
for i := n - 2; i >= 0; i-- {
278+
for j := i + 1; j < n; j++ {
279+
f[i][j] = max(s[j+1]-s[i+1]-f[i+1][j], s[j]-s[i]-f[i][j-1])
280+
}
281+
}
282+
return f[0][n-1]
283+
}
284+
```
285+
286+
```ts
287+
function stoneGameVII(stones: number[]): number {
288+
const n = stones.length;
289+
const s: number[] = Array(n + 1).fill(0);
290+
for (let i = 0; i < n; ++i) {
291+
s[i + 1] = s[i] + stones[i];
292+
}
293+
const f: number[][] = Array.from({ length: n }, () => Array(n).fill(0));
294+
for (let i = n - 2; ~i; --i) {
295+
for (let j = i + 1; j < n; ++j) {
296+
f[i][j] = Math.max(s[j + 1] - s[i + 1] - f[i + 1][j], s[j] - s[i] - f[i][j - 1]);
297+
}
298+
}
299+
return f[0][n - 1];
300+
}
301+
```
302+
164303
<!-- tabs:end -->
165304

166305
<!-- end -->

‎solution/1600-1699/1690.Stone Game VII/Solution.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
class Solution:
22
def stoneGameVII(self, stones: List[int]) -> int:
33
@cache
4-
def dfs(i, j):
4+
def dfs(i: int, j: int) -> int:
55
if i > j:
66
return 0
77
a = s[j + 1] - s[i + 1] - dfs(i + 1, j)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
function stoneGameVII(stones: number[]): number {
2+
const n = stones.length;
3+
const s: number[] = Array(n + 1).fill(0);
4+
for (let i = 0; i < n; ++i) {
5+
s[i + 1] = s[i] + stones[i];
6+
}
7+
const f: number[][] = Array.from({ length: n }, () => Array(n).fill(0));
8+
const dfs = (i: number, j: number): number => {
9+
if (i > j) {
10+
return 0;
11+
}
12+
if (f[i][j]) {
13+
return f[i][j];
14+
}
15+
const a = s[j + 1] - s[i + 1] - dfs(i + 1, j);
16+
const b = s[j] - s[i] - dfs(i, j - 1);
17+
return (f[i][j] = Math.max(a, b));
18+
};
19+
return dfs(0, n - 1);
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class Solution {
2+
public:
3+
int stoneGameVII(vector<int>& stones) {
4+
int n = stones.size();
5+
int s[n + 1];
6+
memset(s, 0, sizeof(s));
7+
for (int i = 0; i < n; ++i) {
8+
s[i + 1] = s[i] + stones[i];
9+
}
10+
int f[n][n];
11+
memset(f, 0, sizeof(f));
12+
for (int i = n - 2; i >= 0; --i) {
13+
for (int j = i + 1; j < n; ++j) {
14+
int a = s[j + 1] - s[i + 1] - f[i + 1][j];
15+
int b = s[j] - s[i] - f[i][j - 1];
16+
f[i][j] = max(a, b);
17+
}
18+
}
19+
return f[0][n - 1];
20+
}
21+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
func stoneGameVII(stones []int) int {
2+
n := len(stones)
3+
s := make([]int, n+1)
4+
for i, x := range stones {
5+
s[i+1] = s[i] + x
6+
}
7+
f := make([][]int, n)
8+
for i := range f {
9+
f[i] = make([]int, n)
10+
}
11+
for i := n - 2; i >= 0; i-- {
12+
for j := i + 1; j < n; j++ {
13+
f[i][j] = max(s[j+1]-s[i+1]-f[i+1][j], s[j]-s[i]-f[i][j-1])
14+
}
15+
}
16+
return f[0][n-1]
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class Solution {
2+
public int stoneGameVII(int[] stones) {
3+
int n = stones.length;
4+
int[] s = new int[n + 1];
5+
for (int i = 0; i < n; ++i) {
6+
s[i + 1] = s[i] + stones[i];
7+
}
8+
int[][] f = new int[n][n];
9+
for (int i = n - 2; i >= 0; --i) {
10+
for (int j = i + 1; j < n; ++j) {
11+
int a = s[j + 1] - s[i + 1] - f[i + 1][j];
12+
int b = s[j] - s[i] - f[i][j - 1];
13+
f[i][j] = Math.max(a, b);
14+
}
15+
}
16+
return f[0][n - 1];
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Solution:
2+
def stoneGameVII(self, stones: List[int]) -> int:
3+
s = list(accumulate(stones, initial=0))
4+
n = len(stones)
5+
f = [[0] * n for _ in range(n)]
6+
for i in range(n - 2, -1, -1):
7+
for j in range(i + 1, n):
8+
a = s[j + 1] - s[i + 1] - f[i + 1][j]
9+
b = s[j] - s[i] - f[i][j - 1]
10+
f[i][j] = max(a, b)
11+
return f[0][-1]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
function stoneGameVII(stones: number[]): number {
2+
const n = stones.length;
3+
const s: number[] = Array(n + 1).fill(0);
4+
for (let i = 0; i < n; ++i) {
5+
s[i + 1] = s[i] + stones[i];
6+
}
7+
const f: number[][] = Array.from({ length: n }, () => Array(n).fill(0));
8+
for (let i = n - 2; ~i; --i) {
9+
for (let j = i + 1; j < n; ++j) {
10+
f[i][j] = Math.max(s[j + 1] - s[i + 1] - f[i + 1][j], s[j] - s[i] - f[i][j - 1]);
11+
}
12+
}
13+
return f[0][n - 1];
14+
}

0 commit comments

Comments
 (0)
Please sign in to comment.