99
99
100
100
<!-- solution:start -->
101
101
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$ 是盒子的总数。
103
120
104
121
<!-- tabs:start -->
105
122
@@ -115,25 +132,31 @@ class Solution:
115
132
containedBoxes : List[List[int ]],
116
133
initialBoxes : List[int ],
117
134
) -> 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]
123
144
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]
137
160
return ans
138
161
```
139
162
@@ -143,35 +166,36 @@ class Solution:
143
166
class Solution {
144
167
public int maxCandies (
145
168
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];
150
169
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];
157
179
}
158
180
}
159
181
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
+ }
167
191
}
168
192
}
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] ;
175
199
}
176
200
}
177
201
}
@@ -185,40 +209,50 @@ class Solution {
185
209
``` cpp
186
210
class Solution {
187
211
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) {
193
218
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];
200
228
}
201
229
}
230
+
202
231
while (!q.empty()) {
203
- int i = q.front();
232
+ int box = q.front();
204
233
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
+ }
211
243
}
212
244
}
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];
219
252
}
220
253
}
221
254
}
255
+
222
256
return ans;
223
257
}
224
258
};
@@ -227,41 +261,147 @@ public:
227
261
#### Go
228
262
229
263
``` 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]
242
274
}
243
275
}
244
276
for len (q) > 0 {
245
- i := q[0]
277
+ box := q[0 ]
246
278
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
+ }
253
287
}
254
288
}
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]
261
295
}
262
296
}
263
297
}
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
+ }
265
405
}
266
406
```
267
407
0 commit comments