Skip to content

Commit 0a017c9

Browse files
authored
feat: add solutions to lc problem: No.3466 (#4108)
No.3466.Maximum Coin Collection
1 parent 4ea435c commit 0a017c9

File tree

13 files changed

+798
-11
lines changed

13 files changed

+798
-11
lines changed

solution/0700-0799/0768.Max Chunks To Make Sorted II/README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ tags:
3333
<strong>输入:</strong>arr = [5,4,3,2,1]
3434
<strong>输出:</strong>1
3535
<strong>解释:</strong>
36-
将数组分成2块或者更多块,都无法得到所需的结果。
37-
例如,分成 [5, 4], [3, 2, 1] 的结果是 [4, 5, 1, 2, 3],这不是有序的数组。
36+
将数组分成2块或者更多块,都无法得到所需的结果。
37+
例如,分成 [5, 4], [3, 2, 1] 的结果是 [4, 5, 1, 2, 3],这不是有序的数组。
3838
</pre>
3939

4040
<p><strong class="example">示例 2:</strong></p>
@@ -43,8 +43,8 @@ tags:
4343
<strong>输入:</strong>arr = [2,1,3,4,4]
4444
<strong>输出:</strong>4
4545
<strong>解释:</strong>
46-
可以把它分成两块,例如 [2, 1], [3, 4, 4]。
47-
然而,分成 [2, 1], [3], [4], [4] 可以得到最多的块数。
46+
可以把它分成两块,例如 [2, 1], [3, 4, 4]。
47+
然而,分成 [2, 1], [3], [4], [4] 可以得到最多的块数。
4848
</pre>
4949

5050
<p>&nbsp;</p>

solution/0700-0799/0779.K-th Symbol in Grammar/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ tags:
4040
<pre>
4141
<strong>输入:</strong> n = 2, k = 1
4242
<strong>输出:</strong> 0
43-
<strong>解释:</strong>
44-
第一行: 0
43+
<strong>解释:</strong>
44+
第一行: 0
4545
第二行: <u>0</u>1
4646
</pre>
4747

solution/0700-0799/0779.K-th Symbol in Grammar/README_EN.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ tags:
4040
<pre>
4141
<strong>Input:</strong> n = 2, k = 1
4242
<strong>Output:</strong> 0
43-
<strong>Explanation:</strong>
43+
<strong>Explanation:</strong>
4444
row 1: 0
4545
row 2: <u>0</u>1
4646
</pre>
@@ -50,7 +50,7 @@ row 2: <u>0</u>1
5050
<pre>
5151
<strong>Input:</strong> n = 2, k = 2
5252
<strong>Output:</strong> 1
53-
<strong>Explanation:</strong>
53+
<strong>Explanation:</strong>
5454
row 1: 0
5555
row 2: 0<u>1</u>
5656
</pre>

solution/0700-0799/0781.Rabbits in Forest/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ tags:
3131
<strong>输入:</strong>answers = [1,1,2]
3232
<strong>输出:</strong>5
3333
<strong>解释:</strong>
34-
两只回答了 "1" 的兔子可能有相同的颜色,设为红色。
34+
两只回答了 "1" 的兔子可能有相同的颜色,设为红色。
3535
之后回答了 "2" 的兔子不会是红色,否则他们的回答会相互矛盾。
36-
设回答了 "2" 的兔子为蓝色。
37-
此外,森林中还应有另外 2 只蓝色兔子的回答没有包含在数组中。
36+
设回答了 "2" 的兔子为蓝色。
37+
此外,森林中还应有另外 2 只蓝色兔子的回答没有包含在数组中。
3838
因此森林中兔子的最少数量是 5 只:3 只回答的和 2 只没有回答的。
3939
</pre>
4040

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
---
2+
comments: true
3+
difficulty: 中等
4+
edit_url: https://github.com/doocs/leetcode/edit/main/solution/3400-3499/3466.Maximum%20Coin%20Collection/README.md
5+
---
6+
7+
<!-- problem:start -->
8+
9+
# [3466. 最大硬币收藏量 🔒](https://leetcode.cn/problems/maximum-coin-collection)
10+
11+
[English Version](/solution/3400-3499/3466.Maximum%20Coin%20Collection/README_EN.md)
12+
13+
## 题目描述
14+
15+
<!-- description:start -->
16+
17+
<p>Mario 在双车道高速公路上行驶,每英里都有硬币。给定两个整数数组,<code>lane1</code> 和&nbsp;<code>lane2</code>,其中第&nbsp;<code>i</code>&nbsp;个下标的值表示他在车道上处于第&nbsp;<code>i</code>&nbsp;英里时获得或失去的硬币数量。</p>
18+
19+
<ul>
20+
<li>如果&nbsp;Mario 在车道 1 上处于&nbsp;<code>i</code> 英里处,并且&nbsp;<code>lane1[i] &gt; 0</code>,Mario 获得&nbsp;<code>lane1[i]</code> 硬币。</li>
21+
<li>如果 Mario 在车道 1 上处于&nbsp;<code>i</code>&nbsp;英里处,并且&nbsp;<code>lane1[i] &lt; 0</code>,Mario 支付通行费并失去&nbsp;<code>abs(lane1[i])</code>&nbsp;个硬币。</li>
22+
<li>规则同样对&nbsp;<code>lane2</code>&nbsp;适用。</li>
23+
</ul>
24+
25+
<p>Mario&nbsp;可以在任何地方进入高速公路,并在行驶 <strong>至少</strong> 一英里后随时退出。Mario 总是从 1 号车道进入高速公路,但 <strong>最多</strong> 可以换道 2 次。</p>
26+
27+
<p><strong>换道</strong>&nbsp;是指 Mario 从车道 1 换到车道 2,反之亦然。</p>
28+
29+
<p>返回 Mario 在进行&nbsp;<strong>最多 2 次换道</strong>&nbsp;&nbsp;<strong>最多</strong>&nbsp;可以获得的硬币数。</p>
30+
31+
<p><strong>注意:</strong>Mario&nbsp;可以在进入高速公路或退出高速公路之前立即切换车道。</p>
32+
33+
<p>&nbsp;</p>
34+
35+
<p><strong class="example">示例 1:</strong></p>
36+
37+
<div class="example-block">
38+
<p><span class="example-io"><b>输入:</b>lane1 = [1,-2,-10,3], lane2 = [-5,10,0,1]</span></p>
39+
40+
<p><span class="example-io"><b>输出:</b>14</span></p>
41+
42+
<p><strong>解释:</strong></p>
43+
44+
<ul>
45+
<li>Mario 在车道 1 上行驶了第 1 英里。</li>
46+
<li>接着,他切换到车道 2 并继续行驶 2 英里。</li>
47+
<li>最后 1 英里他切换回了车道 1。</li>
48+
</ul>
49+
50+
<p>Mario 收集了&nbsp;<code>1 + 10 + 0 + 3 = 14</code> 硬币。</p>
51+
</div>
52+
53+
<p><strong class="example">示例 2:</strong></p>
54+
55+
<div class="example-block">
56+
<p><span class="example-io"><b>输入:</b>lane1 = [1,-1,-1,-1], lane2 = [0,3,4,-5]</span></p>
57+
58+
<p><span class="example-io"><b>输出:</b>8</span></p>
59+
60+
<p><strong>解释:</strong></p>
61+
62+
<ul>
63+
<li>Mario 从 0 英里处进入车道 1 并行驶了 1 英里。</li>
64+
<li>接着,他切换到车道 2 并继续行驶了 2 英里。他在 3 英里处离开高速公路。</li>
65+
</ul>
66+
67+
<p>他总共收集了&nbsp;<code>1 + 3 + 4 = 8</code> 硬币。</p>
68+
</div>
69+
70+
<p><strong class="example">示例 3:</strong></p>
71+
72+
<div class="example-block">
73+
<p><span class="example-io"><b>输入:</b>lane1 = [-5,-4,-3], lane2 = [-1,2,3]</span></p>
74+
75+
<p><span class="example-io"><b>输出:</b>5</span></p>
76+
77+
<p><strong>解释:</strong></p>
78+
79+
<ul>
80+
<li>Mario 从 1 英里处进入并立即切换到车道 2。他全程保持在这根车道上。</li>
81+
</ul>
82+
83+
<p>他总共收集了&nbsp;<code>2 + 3 = 5</code>&nbsp;硬币。</p>
84+
</div>
85+
86+
<p><strong class="example">示例 4:</strong></p>
87+
88+
<div class="example-block">
89+
<p><span class="example-io"><b>输入:</b>lane1 = [-3,-3,-3], lane2 = [9,-2,4]</span></p>
90+
91+
<p><b>输出:</b>11</p>
92+
93+
<p><strong>解释:</strong></p>
94+
95+
<ul>
96+
<li>Mario 从高速公路的开头进入并立即切换到车道 2。他全程保持在这根车道上。</li>
97+
</ul>
98+
99+
<p>他总共获得了&nbsp;<code>9 + (-2) + 4 = 11</code> 硬币。</p>
100+
</div>
101+
102+
<p><strong class="example">示例 5:</strong></p>
103+
104+
<div class="example-block">
105+
<p><span class="example-io"><b>输入:</b>lane1 = [-10], lane2 = [-2]</span></p>
106+
107+
<p><span class="example-io"><b>输出:</b>-2</span></p>
108+
109+
<p><strong>解释:</strong></p>
110+
111+
<ul>
112+
<li>由于 Mario 必须在高速公路上行驶至少 1 英里,他只在车道 2 上行驶了 1 英里。</li>
113+
</ul>
114+
115+
<p>他总共获得了 -2 硬币。</p>
116+
</div>
117+
118+
<p>&nbsp;</p>
119+
120+
<p><strong>提示:</strong></p>
121+
122+
<ul>
123+
<li><code>1 &lt;= lane1.length == lane2.length &lt;= 10<sup>5</sup></code></li>
124+
<li><code>-10<sup>9</sup> &lt;= lane1[i], lane2[i] &lt;= 10<sup>9</sup></code></li>
125+
</ul>
126+
127+
<!-- description:end -->
128+
129+
## 解法
130+
131+
<!-- solution:start -->
132+
133+
### 方法一:记忆化搜索
134+
135+
我们设计一个函数 $\textit{dfs}(i, j, k)$,表示 Mario 从第 $i$ 个位置开始,当前在第 $j$ 条车道上,还可以换道 $k$ 次的情况下,最多可以获得的硬币数。那么答案就是对于所有的 $i$,取 $\textit{dfs}(i, 0, 2)$ 的最大值。
136+
137+
函数 $\textit{dfs}(i, j, k)$ 的计算方式如下:
138+
139+
- 如果 $i \geq n$,表示已经走到了终点,返回 0;
140+
- 如果不变道,当前可以行驶 1 英里,然后驶出,或者继续行驶,取两者中的最大值,即 $\max(x, \textit{dfs}(i + 1, j, k) + x)$;
141+
- 如果可以变道,有两种选择,一种是行驶 1 英里,然后变道,另一种是直接变道,取这两种情况的最大值,即 $\max(\textit{dfs}(i + 1, j \oplus 1, k - 1) + x, \textit{dfs}(i, j \oplus 1, k - 1))$。
142+
- 其中 $x$ 表示当前位置的硬币数。
143+
144+
为了避免重复计算,我们使用记忆化搜索的方法,将已经计算过的结果保存下来。
145+
146+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 表示车道的长度。
147+
148+
<!-- tabs:start -->
149+
150+
#### Python3
151+
152+
```python
153+
class Solution:
154+
def maxCoins(self, lane1: List[int], lane2: List[int]) -> int:
155+
@cache
156+
def dfs(i: int, j: int, k: int) -> int:
157+
if i >= n:
158+
return 0
159+
x = lane1[i] if j == 0 else lane2[i]
160+
ans = max(x, dfs(i + 1, j, k) + x)
161+
if k > 0:
162+
ans = max(ans, dfs(i + 1, j ^ 1, k - 1) + x)
163+
ans = max(ans, dfs(i, j ^ 1, k - 1))
164+
return ans
165+
166+
n = len(lane1)
167+
ans = -inf
168+
for i in range(n):
169+
ans = max(ans, dfs(i, 0, 2))
170+
return ans
171+
```
172+
173+
#### Java
174+
175+
```java
176+
class Solution {
177+
private int n;
178+
private int[] lane1;
179+
private int[] lane2;
180+
private Long[][][] f;
181+
182+
public long maxCoins(int[] lane1, int[] lane2) {
183+
n = lane1.length;
184+
this.lane1 = lane1;
185+
this.lane2 = lane2;
186+
f = new Long[n][2][3];
187+
long ans = Long.MIN_VALUE;
188+
for (int i = 0; i < n; ++i) {
189+
ans = Math.max(ans, dfs(i, 0, 2));
190+
}
191+
return ans;
192+
}
193+
194+
private long dfs(int i, int j, int k) {
195+
if (i >= n) {
196+
return 0;
197+
}
198+
if (f[i][j][k] != null) {
199+
return f[i][j][k];
200+
}
201+
int x = j == 0 ? lane1[i] : lane2[i];
202+
long ans = Math.max(x, dfs(i + 1, j, k) + x);
203+
if (k > 0) {
204+
ans = Math.max(ans, dfs(i + 1, j ^ 1, k - 1) + x);
205+
ans = Math.max(ans, dfs(i, j ^ 1, k - 1));
206+
}
207+
return f[i][j][k] = ans;
208+
}
209+
}
210+
```
211+
212+
#### C++
213+
214+
```cpp
215+
class Solution {
216+
public:
217+
long long maxCoins(vector<int>& lane1, vector<int>& lane2) {
218+
int n = lane1.size();
219+
long long ans = -1e18;
220+
vector<vector<vector<long long>>> f(n, vector<vector<long long>>(2, vector<long long>(3, -1e18)));
221+
auto dfs = [&](this auto&& dfs, int i, int j, int k) -> long long {
222+
if (i >= n) {
223+
return 0LL;
224+
}
225+
if (f[i][j][k] != -1e18) {
226+
return f[i][j][k];
227+
}
228+
int x = j == 0 ? lane1[i] : lane2[i];
229+
long long ans = max((long long) x, dfs(i + 1, j, k) + x);
230+
if (k > 0) {
231+
ans = max(ans, dfs(i + 1, j ^ 1, k - 1) + x);
232+
ans = max(ans, dfs(i, j ^ 1, k - 1));
233+
}
234+
return f[i][j][k] = ans;
235+
};
236+
for (int i = 0; i < n; ++i) {
237+
ans = max(ans, dfs(i, 0, 2));
238+
}
239+
return ans;
240+
}
241+
};
242+
```
243+
244+
#### Go
245+
246+
```go
247+
func maxCoins(lane1 []int, lane2 []int) int64 {
248+
n := len(lane1)
249+
f := make([][2][3]int64, n)
250+
for i := range f {
251+
for j := range f[i] {
252+
for k := range f[i][j] {
253+
f[i][j][k] = -1
254+
}
255+
}
256+
}
257+
var dfs func(int, int, int) int64
258+
dfs = func(i, j, k int) int64 {
259+
if i >= n {
260+
return 0
261+
}
262+
if f[i][j][k] != -1 {
263+
return f[i][j][k]
264+
}
265+
x := int64(lane1[i])
266+
if j == 1 {
267+
x = int64(lane2[i])
268+
}
269+
ans := max(x, dfs(i+1, j, k)+x)
270+
if k > 0 {
271+
ans = max(ans, dfs(i+1, j^1, k-1)+x)
272+
ans = max(ans, dfs(i, j^1, k-1))
273+
}
274+
f[i][j][k] = ans
275+
return ans
276+
}
277+
ans := int64(-1e18)
278+
for i := range lane1 {
279+
ans = max(ans, dfs(i, 0, 2))
280+
}
281+
return ans
282+
}
283+
```
284+
285+
#### TypeScript
286+
287+
```ts
288+
function maxCoins(lane1: number[], lane2: number[]): number {
289+
const n = lane1.length;
290+
const NEG_INF = -1e18;
291+
const f: number[][][] = Array.from({ length: n }, () =>
292+
Array.from({ length: 2 }, () => Array(3).fill(NEG_INF)),
293+
);
294+
const dfs = (dfs: Function, i: number, j: number, k: number): number => {
295+
if (i >= n) {
296+
return 0;
297+
}
298+
if (f[i][j][k] !== NEG_INF) {
299+
return f[i][j][k];
300+
}
301+
const x = j === 0 ? lane1[i] : lane2[i];
302+
let ans = Math.max(x, dfs(dfs, i + 1, j, k) + x);
303+
if (k > 0) {
304+
ans = Math.max(ans, dfs(dfs, i + 1, j ^ 1, k - 1) + x);
305+
ans = Math.max(ans, dfs(dfs, i, j ^ 1, k - 1));
306+
}
307+
f[i][j][k] = ans;
308+
return ans;
309+
};
310+
let ans = NEG_INF;
311+
for (let i = 0; i < n; ++i) {
312+
ans = Math.max(ans, dfs(dfs, i, 0, 2));
313+
}
314+
return ans;
315+
}
316+
```
317+
318+
<!-- tabs:end -->
319+
320+
<!-- solution:end -->
321+
322+
<!-- problem:end -->

0 commit comments

Comments
 (0)