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:
143166class 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
186210class Solution {
187211public:
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