There are k workers who want to move n boxes from the right (old) warehouse to the left (new) warehouse. You are given the two integers n and k, and a 2D integer array time of size k x 4 where time[i] = [righti, picki, lefti, puti].
The warehouses are separated by a river and connected by a bridge. Initially, all k workers are waiting on the left side of the bridge. To move the boxes, the ith worker can do the following:
righti minutes.picki minutes.lefti minutes.puti minutes.The ith worker is less efficient than the jth worker if either condition is met:
lefti + righti > leftj + rightjlefti + righti == leftj + rightj and i > jThe following rules regulate the movement of the workers through the bridge:
Return the elapsed minutes at which the last box reaches the left side of the bridge.
Example 1:
Input: n = 1, k = 3, time = [[1,1,2,1],[1,1,3,1],[1,1,4,1]]
Output: 6
Explanation:
From 0 to 1 minutes: worker 2 crosses the bridge to the right. From 1 to 2 minutes: worker 2 picks up a box from the right warehouse. From 2 to 6 minutes: worker 2 crosses the bridge to the left. From 6 to 7 minutes: worker 2 puts a box at the left warehouse. The whole process ends after 7 minutes. We return 6 because the problem asks for the instance of time at which the last worker reaches the left side of the bridge.
Example 2:
Input: n = 3, k = 2, time = [[1,5,1,8],[10,10,10,10]]
Output: 37
Explanation:
The last box reaches the left side at 37 seconds. Notice, how we do not put the last boxes down, as that would take more time, and they are already on the left with the workers.
Constraints:
1 <= n, k <= 104time.length == ktime[i].length == 41 <= lefti, picki, righti, puti <= 1000When 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 method for figuring out the fastest way to get everyone across the bridge involves checking absolutely every possible order in which people could cross. We consider all combinations, even the really slow ones, until we find the quickest.
Here's how the algorithm would work step-by-step:
def time_to_cross_a_bridge_brute_force(people_crossing_times):
fastest_time = float('inf')
def find_min_time(left_side, right_side, flashlight_on_left, current_time):
nonlocal fastest_time
if not left_side:
# Base case: everyone is on the right side
fastest_time = min(fastest_time, current_time)
return
if flashlight_on_left:
# Explore all possible pairs crossing to the right
for i in range(len(left_side)):
for j in range(i + 1, len(left_side)):
# This ensures that the same person never crosses with themselves
crossing_pair = [left_side[i], left_side[j]]
remaining_left = left_side[:i] + left_side[i+1:j] + left_side[j+1:]
crossing_time = max(crossing_pair)
# Explore all possible people returning with the flashlight
for returning_person in crossing_pair:
new_right_side = right_side + crossing_pair
new_right_side.sort()
return_time = returning_person
find_min_time(sorted(remaining_left + [returning_person]), sorted([person for person in new_right_side if person not in crossing_pair or person == returning_person and new_right_side.count(person) == 1]), False, current_time + crossing_time + return_time)
else:
# Explore all possible people crossing to the left
for person_returning in right_side:
#Only one person returns with the flashlight.
remaining_right = right_side[:right_side.index(person_returning)] + right_side[right_side.index(person_returning)+1:]
return_time = person_returning
# This moves one person from right to left.
find_min_time(sorted(left_side + [person_returning]), sorted(remaining_right), True, current_time + return_time)
# Begin with everyone on the left side
find_min_time(sorted(people_crossing_times), [], True, 0)
return fastest_timeThe key idea is to recognize that the fastest two people should be helping the slower ones cross. We want to minimize the time the two fastest people spend going back and forth.
Here's how the algorithm would work step-by-step:
def time_to_cross_a_bridge(people_crossing_times):
people_crossing_times.sort()
number_of_people = len(people_crossing_times)
total_time = 0
while number_of_people > 0:
if number_of_people == 1:
total_time += people_crossing_times[0]
number_of_people -= 1
elif number_of_people == 2:
total_time += people_crossing_times[1]
number_of_people -= 2
else:
# Determine the fastest two and slowest two
fastest_person = people_crossing_times[0]
second_fastest_person = people_crossing_times[1]
slowest_person = people_crossing_times[-1]
second_slowest_person = people_crossing_times[-2]
# Calculate the two strategies.
strategy_one_time = second_fastest_person + fastest_person + \
slowest_person + second_fastest_person
strategy_two_time = fastest_person + slowest_person + \
fastest_person + second_slowest_person
# This picks the optimal strategy for crossing.
if strategy_one_time < strategy_two_time:
total_time += strategy_one_time
else:
total_time += strategy_two_time
# Remove the slowest two people from the list.
people_crossing_times = people_crossing_times[:-2]
number_of_people -= 2
return total_time| Case | How to Handle |
|---|---|
| workers is zero or negative | Return 0 if the number of workers is zero and throw an exception if negative, as no crossing is possible. |
| bridge length is zero or negative | Return 0 if the bridge length is zero and throw an exception if negative, as no crossing is possible. |
| Individual times or pair times are zero | If individual time is zero, worker instantly crosses; if pair time is zero, handle appropriately during pair selection, ensuring not dividing by zero. |
| times array is null or empty | Throw an IllegalArgumentException if the arrays are null or empty to prevent NullPointerExceptions or incorrect processing. |
| Number of workers is greater than the length of the times array. | Handle only available workers, adjusting based on the number of workers provided vs. the length of the `times` array. |
| Workers times contains large numbers | Use `long` data type to prevent integer overflow when calculating the total time and intermediate sums. |
| All workers have the same crossing time | Optimize the pairing strategy, possibly always sending the two slowest, since individual differences won't matter. |
| Only one worker | Return the single worker's individual crossing time as the result, avoiding pairing logic. |