You have n
boxes labeled from 0
to n - 1
. You are given four arrays: status
, candies
, keys
, and containedBoxes
where:
status[i]
is 1
if the ith
box is open and 0
if the ith
box is closed,candies[i]
is the number of candies in the ith
box,keys[i]
is a list of the labels of the boxes you can open after opening the ith
box.containedBoxes[i]
is a list of the boxes you found inside the ith
box.You are given an integer array initialBoxes
that contains the labels of the boxes you initially have. You can take all the candies in any open box and you can use the keys in it to open new boxes and you also can use the boxes you find in it.
Return the maximum number of candies you can get following the rules above.
Example 1:
Input: status = [1,0,1,0], candies = [7,5,4,100], keys = [[],[],[1],[]], containedBoxes = [[1,2],[3],[],[]], initialBoxes = [0] Output: 16 Explanation: You will be initially given box 0. You will find 7 candies in it and boxes 1 and 2. Box 1 is closed and you do not have a key for it so you will open box 2. You will find 4 candies and a key to box 1 in box 2. In box 1, you will find 5 candies and box 3 but you will not find a key to box 3 so box 3 will remain closed. Total number of candies collected = 7 + 4 + 5 = 16 candy.
Example 2:
Input: status = [1,0,0,0,0,0], candies = [1,1,1,1,1,1], keys = [[1,2,3,4,5],[],[],[],[],[]], containedBoxes = [[1,2,3,4,5],[],[],[],[],[]], initialBoxes = [0] Output: 6 Explanation: You have initially box 0. Opening it you can find boxes 1,2,3,4 and 5 and their keys. The total number of candies will be 6.
Constraints:
n == status.length == candies.length == keys.length == containedBoxes.length
1 <= n <= 1000
status[i]
is either 0
or 1
.1 <= candies[i] <= 1000
0 <= keys[i].length <= n
0 <= keys[i][j] < n
keys[i]
are unique.0 <= containedBoxes[i].length <= n
0 <= containedBoxes[i][j] < n
containedBoxes[i]
are unique.0 <= initialBoxes.length <= n
0 <= initialBoxes[i] < n
This problem involves finding the maximum number of candies obtainable from a set of boxes, given constraints on box opening and contents. The solution uses a breadth-first search (BFS) approach to efficiently explore all possible candy collections.
Approach:
Initialization:
q
) containing only the initially accessible boxes (those in initialBoxes
that are already open, status[i] == 1
).ans
stores the total candies collected. It's initialized with candies from initially open boxes.has
is a set tracking boxes we've encountered (regardless of whether they're open). This handles boxes found inside other boxes.took
is a set to keep track of boxes from which we have already collected candies. This avoids recounting candies.BFS Traversal:
while
loop continues as long as the queue is not empty.i
).keys[i]
) found in box i
. If a key opens a new box (status[k] = 1
) and that box has been encountered (has[k]
) but not yet processed (!took[k]
), we add its candies to ans
, mark it as processed (took[k]
), and add it to the queue for further exploration.containedBoxes[i]
) found inside box i
. If a contained box has been encountered (has[j]
), is open (status[j] == 1
), and hasn't been processed (!took[j]
), we collect its candies, mark it as processed, and enqueue it.Return Value:
ans
(the total candies collected) is returned.Time Complexity: O(N), where N is the number of boxes. In the worst case, we might visit each box once. The operations within the loop (checking sets, adding to queue) are O(1) on average for hash sets and queues.
Space Complexity: O(N) The space is dominated by the q
, has
, and took
data structures, each of which could potentially store up to N elements in the worst case.
from collections import deque
class Solution:
def maxCandies(self, status, candies, keys, containedBoxes, initialBoxes):
q = deque([i for i in initialBoxes if status[i] == 1]) # Start with open initial boxes
ans = sum(candies[i] for i in initialBoxes if status[i] == 1) # Initial candy count
has = set(initialBoxes) # Set of encountered boxes
took = {i for i in initialBoxes if status[i] == 1} # Set of processed boxes
while q:
i = q.popleft() # Get the next box
for k in keys[i]: # Process keys
status[k] = 1 # Open the box using the key
if k in has and k not in took: # If encountered but not processed
ans += candies[k] # Collect candies
took.add(k) # Mark as processed
q.append(k) # Add to queue
for j in containedBoxes[i]: # Process contained boxes
has.add(j) # Mark as encountered
if status[j] and j not in took: # If open and not processed
ans += candies[j] # Collect candies
took.add(j) # Mark as processed
q.append(j) # Add to queue
return ans
The other languages (Java, C++, Go) follow the same logical structure, utilizing their respective queue and set implementations. The core algorithm remains consistent across all languages.