Skip to content

Commit 3a37346

Browse files
committed
feat: add solutions to lc problem: No.1298
No.1298.Maximum Candies You Can Get from Boxes
1 parent 9716c9c commit 3a37346

File tree

8 files changed

+670
-277
lines changed

8 files changed

+670
-277
lines changed

solution/1200-1299/1298.Maximum Candies You Can Get from Boxes/README.md

Lines changed: 232 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,24 @@ tags:
9999

100100
<!-- solution:start -->
101101

102-
### 方法一:BFS
102+
### 方法一:BFS + 哈希集合
103+
104+
题目给定一批盒子,每个盒子可能有状态(开/关)、糖果、钥匙、以及其他盒子。我们的目标是通过初始给定的一些盒子,尽可能多地打开更多盒子,并收集其中的糖果。可以通过获得钥匙来解锁新盒子,通过盒子中嵌套的盒子来获取更多资源。
105+
106+
我们采用 BFS 的方式模拟整个探索过程。
107+
108+
我们用一个队列 $q$ 表示当前可以访问的、**已经开启** 的盒子;用两个集合 $\textit{has}$ 和 $\textit{took}$ 分别记录**我们拥有的所有盒子****已经处理过的盒子**,防止重复。
109+
110+
初始时,将所有 $\textit{initialBoxes}$ 添加到 $\textit{has}$ 中,如果初始盒子状态为开启,立即加入队列 $\textit{q}$ 并累计糖果;
111+
112+
然后进行 BFS,依次从 $\textit{q}$ 中取出盒子:
113+
114+
- 获取盒子中的钥匙 $\textit{keys[box]}$,将能解锁的盒子加入队列;
115+
- 收集盒子中包含的其他盒子 $\textit{containedBoxes[box]}$,如果状态是开启的且未处理过,则立即处理;
116+
117+
每个盒子最多处理一次,糖果累计一次,最终返回总糖果数 $\textit{ans}$。
118+
119+
时间复杂度 $O(n)$,空间复杂度 $O(n)$,其中 $n$ 是盒子的总数。
103120

104121
<!-- tabs:start -->
105122

@@ -115,25 +132,31 @@ class Solution:
115132
containedBoxes: List[List[int]],
116133
initialBoxes: List[int],
117134
) -> int:
118-
q = deque([i for i in initialBoxes if status[i] == 1])
119-
ans = sum(candies[i] for i in initialBoxes if status[i] == 1)
120-
has = set(initialBoxes)
121-
took = {i for i in initialBoxes if status[i] == 1}
122-
135+
q = deque()
136+
has, took = set(initialBoxes), set()
137+
ans = 0
138+
139+
for box in initialBoxes:
140+
if status[box]:
141+
q.append(box)
142+
took.add(box)
143+
ans += candies[box]
123144
while q:
124-
i = q.popleft()
125-
for k in keys[i]:
126-
status[k] = 1
127-
if k in has and k not in took:
128-
ans += candies[k]
129-
took.add(k)
130-
q.append(k)
131-
for j in containedBoxes[i]:
132-
has.add(j)
133-
if status[j] and j not in took:
134-
ans += candies[j]
135-
took.add(j)
136-
q.append(j)
145+
box = q.popleft()
146+
for k in keys[box]:
147+
if not status[k]:
148+
status[k] = 1
149+
if k in has and k not in took:
150+
q.append(k)
151+
took.add(k)
152+
ans += candies[k]
153+
154+
for b in containedBoxes[box]:
155+
has.add(b)
156+
if status[b] and b not in took:
157+
q.append(b)
158+
took.add(b)
159+
ans += candies[b]
137160
return ans
138161
```
139162

@@ -143,35 +166,36 @@ class Solution:
143166
class Solution {
144167
public int maxCandies(
145168
int[] status, int[] candies, int[][] keys, int[][] containedBoxes, int[] initialBoxes) {
146-
int ans = 0;
147-
int n = status.length;
148-
boolean[] has = new boolean[n];
149-
boolean[] took = new boolean[n];
150169
Deque<Integer> q = new ArrayDeque<>();
151-
for (int i : initialBoxes) {
152-
has[i] = true;
153-
if (status[i] == 1) {
154-
ans += candies[i];
155-
took[i] = true;
156-
q.offer(i);
170+
Set<Integer> has = new HashSet<>();
171+
Set<Integer> took = new HashSet<>();
172+
int ans = 0;
173+
for (int box : initialBoxes) {
174+
has.add(box);
175+
if (status[box] == 1) {
176+
q.offer(box);
177+
took.add(box);
178+
ans += candies[box];
157179
}
158180
}
159181
while (!q.isEmpty()) {
160-
int i = q.poll();
161-
for (int k : keys[i]) {
162-
status[k] = 1;
163-
if (has[k] && !took[k]) {
164-
ans += candies[k];
165-
took[k] = true;
166-
q.offer(k);
182+
int box = q.poll();
183+
for (int k : keys[box]) {
184+
if (status[k] == 0) {
185+
status[k] = 1;
186+
if (has.contains(k) && !took.contains(k)) {
187+
q.offer(k);
188+
took.add(k);
189+
ans += candies[k];
190+
}
167191
}
168192
}
169-
for (int j : containedBoxes[i]) {
170-
has[j] = true;
171-
if (status[j] == 1 && !took[j]) {
172-
ans += candies[j];
173-
took[j] = true;
174-
q.offer(j);
193+
for (int b : containedBoxes[box]) {
194+
has.add(b);
195+
if (status[b] == 1 && !took.contains(b)) {
196+
q.offer(b);
197+
took.add(b);
198+
ans += candies[b];
175199
}
176200
}
177201
}
@@ -185,40 +209,50 @@ class Solution {
185209
```cpp
186210
class Solution {
187211
public:
188-
int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) {
189-
int ans = 0;
190-
int n = status.size();
191-
vector<bool> has(n);
192-
vector<bool> took(n);
212+
int maxCandies(
213+
vector<int>& status,
214+
vector<int>& candies,
215+
vector<vector<int>>& keys,
216+
vector<vector<int>>& containedBoxes,
217+
vector<int>& initialBoxes) {
193218
queue<int> q;
194-
for (int& i : initialBoxes) {
195-
has[i] = true;
196-
if (status[i]) {
197-
ans += candies[i];
198-
took[i] = true;
199-
q.push(i);
219+
unordered_set<int> has, took;
220+
int ans = 0;
221+
222+
for (int box : initialBoxes) {
223+
has.insert(box);
224+
if (status[box]) {
225+
q.push(box);
226+
took.insert(box);
227+
ans += candies[box];
200228
}
201229
}
230+
202231
while (!q.empty()) {
203-
int i = q.front();
232+
int box = q.front();
204233
q.pop();
205-
for (int k : keys[i]) {
206-
status[k] = 1;
207-
if (has[k] && !took[k]) {
208-
ans += candies[k];
209-
took[k] = true;
210-
q.push(k);
234+
235+
for (int k : keys[box]) {
236+
if (!status[k]) {
237+
status[k] = 1;
238+
if (has.count(k) && !took.count(k)) {
239+
q.push(k);
240+
took.insert(k);
241+
ans += candies[k];
242+
}
211243
}
212244
}
213-
for (int j : containedBoxes[i]) {
214-
has[j] = true;
215-
if (status[j] && !took[j]) {
216-
ans += candies[j];
217-
took[j] = true;
218-
q.push(j);
245+
246+
for (int b : containedBoxes[box]) {
247+
has.insert(b);
248+
if (status[b] && !took.count(b)) {
249+
q.push(b);
250+
took.insert(b);
251+
ans += candies[b];
219252
}
220253
}
221254
}
255+
222256
return ans;
223257
}
224258
};
@@ -227,41 +261,147 @@ public:
227261
#### Go
228262

229263
```go
230-
func maxCandies(status []int, candies []int, keys [][]int, containedBoxes [][]int, initialBoxes []int) int {
231-
ans := 0
232-
n := len(status)
233-
has := make([]bool, n)
234-
took := make([]bool, n)
235-
var q []int
236-
for _, i := range initialBoxes {
237-
has[i] = true
238-
if status[i] == 1 {
239-
ans += candies[i]
240-
took[i] = true
241-
q = append(q, i)
264+
func maxCandies(status []int, candies []int, keys [][]int, containedBoxes [][]int, initialBoxes []int) (ans int) {
265+
q := []int{}
266+
has := make(map[int]bool)
267+
took := make(map[int]bool)
268+
for _, box := range initialBoxes {
269+
has[box] = true
270+
if status[box] == 1 {
271+
q = append(q, box)
272+
took[box] = true
273+
ans += candies[box]
242274
}
243275
}
244276
for len(q) > 0 {
245-
i := q[0]
277+
box := q[0]
246278
q = q[1:]
247-
for _, k := range keys[i] {
248-
status[k] = 1
249-
if has[k] && !took[k] {
250-
ans += candies[k]
251-
took[k] = true
252-
q = append(q, k)
279+
for _, k := range keys[box] {
280+
if status[k] == 0 {
281+
status[k] = 1
282+
if has[k] && !took[k] {
283+
q = append(q, k)
284+
took[k] = true
285+
ans += candies[k]
286+
}
253287
}
254288
}
255-
for _, j := range containedBoxes[i] {
256-
has[j] = true
257-
if status[j] == 1 && !took[j] {
258-
ans += candies[j]
259-
took[j] = true
260-
q = append(q, j)
289+
for _, b := range containedBoxes[box] {
290+
has[b] = true
291+
if status[b] == 1 && !took[b] {
292+
q = append(q, b)
293+
took[b] = true
294+
ans += candies[b]
261295
}
262296
}
263297
}
264-
return ans
298+
return
299+
}
300+
```
301+
302+
#### TypeScript
303+
304+
```ts
305+
function maxCandies(
306+
status: number[],
307+
candies: number[],
308+
keys: number[][],
309+
containedBoxes: number[][],
310+
initialBoxes: number[],
311+
): number {
312+
const q: number[] = [];
313+
const has: Set<number> = new Set();
314+
const took: Set<number> = new Set();
315+
let ans = 0;
316+
317+
for (const box of initialBoxes) {
318+
has.add(box);
319+
if (status[box] === 1) {
320+
q.push(box);
321+
took.add(box);
322+
ans += candies[box];
323+
}
324+
}
325+
326+
while (q.length > 0) {
327+
const box = q.pop()!;
328+
329+
for (const k of keys[box]) {
330+
if (status[k] === 0) {
331+
status[k] = 1;
332+
if (has.has(k) && !took.has(k)) {
333+
q.push(k);
334+
took.add(k);
335+
ans += candies[k];
336+
}
337+
}
338+
}
339+
340+
for (const b of containedBoxes[box]) {
341+
has.add(b);
342+
if (status[b] === 1 && !took.has(b)) {
343+
q.push(b);
344+
took.add(b);
345+
ans += candies[b];
346+
}
347+
}
348+
}
349+
350+
return ans;
351+
}
352+
```
353+
354+
#### Rust
355+
356+
```rust
357+
use std::collections::{HashSet, VecDeque};
358+
359+
impl Solution {
360+
pub fn max_candies(
361+
mut status: Vec<i32>,
362+
candies: Vec<i32>,
363+
keys: Vec<Vec<i32>>,
364+
contained_boxes: Vec<Vec<i32>>,
365+
initial_boxes: Vec<i32>,
366+
) -> i32 {
367+
let mut q: VecDeque<i32> = VecDeque::new();
368+
let mut has: HashSet<i32> = HashSet::new();
369+
let mut took: HashSet<i32> = HashSet::new();
370+
let mut ans = 0;
371+
372+
for &box_ in &initial_boxes {
373+
has.insert(box_);
374+
if status[box_ as usize] == 1 {
375+
q.push_back(box_);
376+
took.insert(box_);
377+
ans += candies[box_ as usize];
378+
}
379+
}
380+
381+
while let Some(box_) = q.pop_front() {
382+
for &k in &keys[box_ as usize] {
383+
if status[k as usize] == 0 {
384+
status[k as usize] = 1;
385+
if has.contains(&k) && !took.contains(&k) {
386+
q.push_back(k);
387+
took.insert(k);
388+
ans += candies[k as usize];
389+
}
390+
}
391+
}
392+
393+
for &b in &contained_boxes[box_ as usize] {
394+
has.insert(b);
395+
if status[b as usize] == 1 && !took.contains(&b) {
396+
q.push_back(b);
397+
took.insert(b);
398+
ans += candies[b as usize];
399+
}
400+
}
401+
}
402+
403+
ans
404+
}
265405
}
266406
```
267407

0 commit comments

Comments
 (0)