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
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach for this problem is like trying every possible combination of opening boxes. We explore each possibility to find the maximum number of candies we can get by opening different boxes in different orders.
Here's how the algorithm would work step-by-step:
def max_candies_brute_force(candies, boxes, keys, contained_boxes, initial_boxes):
def get_max_candies(current_boxes, opened_boxes):
max_candies_collected = 0
number_of_boxes = len(current_boxes)
# Consider all possible combinations of opening the current boxes
for i in range(1 << number_of_boxes):
total_candies = 0
new_keys = set()
new_boxes = set()
current_opened_boxes = set(opened_boxes)
# Iterate through the boxes and check if we open them in this combination
for j in range(number_of_boxes):
if (i >> j) & 1:
box_index = current_boxes[j]
# Ensure not opening the box again
if box_index not in current_opened_boxes:
total_candies += candies[box_index]
current_opened_boxes.add(box_index)
# Add keys from opened box
for key in keys[box_index]:
new_keys.add(key)
# Add boxes contained in opened box
for contained_box in contained_boxes[box_index]:
new_boxes.add(contained_box)
# Find newly accessible boxes based on acquired keys
accessible_boxes = []
for box_index in new_boxes:
if box_index not in current_opened_boxes and box_index in new_keys or box_index in initial_boxes:
accessible_boxes.append(box_index)
# Explore further if we found new boxes
if accessible_boxes:
total_candies += get_max_candies(accessible_boxes, current_opened_boxes)
max_candies_collected = max(max_candies_collected, total_candies)
return max_candies_collected
# Start recursion with initial boxes
max_candies = get_max_candies(initial_boxes, set())
return max_candies
This problem is like exploring a maze where you want to collect the most candies. We'll use a strategy to systematically open boxes and collect candies, and we keep track of what keys we have to unlock more boxes. The core idea is to explore boxes as soon as we have the key to open them.
Here's how the algorithm would work step-by-step:
def maximum_candies(candies, boxes, keys, initial_boxes):
number_of_boxes = len(candies)
opened_boxes = [False] * number_of_boxes
available_keys = set()
boxes_to_open = initial_boxes[:] # Copy initial boxes to avoid modifying the input
total_candies = 0
while boxes_to_open:
new_boxes_to_open = []
for box_index in boxes_to_open:
# If we haven't opened the box and have the key
if not opened_boxes[box_index] and box_index in available_keys or box_index in initial_boxes:
opened_boxes[box_index] = True
total_candies += candies[box_index]
# Collect the keys in the box
for key in boxes[box_index]:
available_keys.add(key)
# Add newly unlockable boxes to queue
for new_box_index in range(number_of_boxes):
if new_box_index in available_keys and not opened_boxes[new_box_index]:
new_boxes_to_open.append(new_box_index)
# Prevents infinite loops if no new boxes can be opened
if not new_boxes_to_open:
break
boxes_to_open = new_boxes_to_open
return total_candies
Case | How to Handle |
---|---|
Empty boxes array | Return 0 because there are no boxes to start with, so no candies can be obtained. |
Empty keys array when boxes are available | Start with boxes[0] if initialBoxes[0] is true; otherwise, you cannot open any box and return 0. |
No initial boxes open | If initialBoxes contains all false values and you have keys, the solution should open available boxes iteratively until no new boxes can be opened, or all boxes are visited. |
Circular key dependencies (box A has key to box B, box B has key to box A) | Use a visited set to prevent infinite loops in the BFS/DFS; add a box to visited only if it is openable (either initially open, or key available and has not been visited). |
Integer overflow in candies array | Use a data type with a larger range (e.g., long) to store the total number of candies if candies[i] can be very large, avoid overflow in calculating total candy. |
Maximum number of boxes and keys | Consider using iterative approach (BFS) instead of recursive one (DFS) if the depth of boxes can become very deep in order to avoid StackOverflowError and use a boolean array to track visited boxes efficiently. |
All boxes have zero candies | The algorithm should still correctly open available boxes based on the given keys, returning 0 as the total candies collected. |
A box has a key that opens itself | Handle this as a normal case as the key just opens the box one more time and the visited set prevents re-opening, preventing cycles and ensuring correctness. |