There are n
points on a road you are driving your taxi on. The n
points on the road are labeled from 1
to n
in the direction you are going, and you want to drive from point 1
to point n
to make money by picking up passengers. You cannot change the direction of the taxi.
The passengers are represented by a 0-indexed 2D integer array rides
, where rides[i] = [starti, endi, tipi]
denotes the ith
passenger requesting a ride from point starti
to point endi
who is willing to give a tipi
dollar tip.
For each passenger i
you pick up, you earn endi - starti + tipi
dollars. You may only drive at most one passenger at a time.
Given n
and rides
, return the maximum number of dollars you can earn by picking up the passengers optimally.
Note: You may drop off a passenger and pick up a different passenger at the same point.
Example 1:
Input: n = 5, rides = [[2,5,4],[1,5,1]] Output: 7 Explanation: We can pick up passenger 0 to earn 5 - 2 + 4 = 7 dollars.
Example 2:
Input: n = 20, rides = [[1,6,1],[3,10,2],[10,12,3],[11,12,2],[12,15,2],[13,18,1]] Output: 20 Explanation: We will pick up the following passengers: - Drive passenger 1 from point 3 to point 10 for a profit of 10 - 3 + 2 = 9 dollars. - Drive passenger 2 from point 10 to point 12 for a profit of 12 - 10 + 3 = 5 dollars. - Drive passenger 5 from point 13 to point 18 for a profit of 18 - 13 + 1 = 6 dollars. We earn 9 + 5 + 6 = 20 dollars in total.
Constraints:
1 <= n <= 105
1 <= rides.length <= 3 * 104
rides[i].length == 3
1 <= starti < endi <= n
1 <= tipi <= 105
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 core idea is to explore all possible combinations of taxi ride choices to find the most profitable one. We will look at every possible subset of rides. Then, we'll calculate the earnings for each valid subset and pick the subset that provides maximum earnings.
Here's how the algorithm would work step-by-step:
def max_taxi_earnings_brute_force(number_of_locations, rides):
max_earnings = 0
number_of_rides = len(rides)
# Iterate through all possible subsets of rides
for i in range(1 << number_of_rides):
current_rides = []
# Select the rides for the current subset
for j in range(number_of_rides):
if (i >> j) & 1:
current_rides.append(rides[j])
is_valid = True
# Check if the selected rides are non-overlapping.
for first_ride_index in range(len(current_rides)):
for second_ride_index in range(first_ride_index + 1, len(current_rides)):
start_first, end_first, _ = current_rides[first_ride_index]
start_second, end_second, _ = current_rides[second_ride_index]
#Overlapping rides are invalid
if not (end_first <= start_second or end_second <= start_first):
is_valid = False
break
if not is_valid:
break
#Calculate profit only if valid
if is_valid:
current_earnings = 0
# Sum up the earnings for current valid rides
for ride in current_rides:
start_location, end_location, tip = ride
current_earnings += (end_location - start_location + tip)
# Store the max earning from valid rides
max_earnings = max(max_earnings, current_earnings)
return max_earnings
The optimal strategy for maximizing taxi earnings involves using a technique that builds the best solution step by step, avoiding re-calculations. We aim to find the most profitable route to each possible destination by remembering the best results we've seen so far.
Here's how the algorithm would work step-by-step:
def max_taxi_earnings(number_of_stops, rides):
maximum_earnings_at_stop = [0] * (number_of_stops + 1)
rides.sort()
for start_position, end_position, tip_amount in rides:
# Determine profit for the current ride.
ride_profit = end_position - start_position + tip_amount
# See if taking the current ride leads to more profit.
potential_earnings = maximum_earnings_at_stop[start_position] + ride_profit
# Keep the maximum earnings seen so far.
maximum_earnings_at_stop[end_position] = max(maximum_earnings_at_stop[end_position], potential_earnings)
for i in range(end_position + 1, number_of_stops + 1):
maximum_earnings_at_stop[i] = max(maximum_earnings_at_stop[i], maximum_earnings_at_stop[end_position])
return maximum_earnings_at_stop[number_of_stops]
Case | How to Handle |
---|---|
Empty rides array | Return 0 as no rides mean no earnings. |
n = 1 and rides exist, but only start/end at location 1 | The solution should still process valid rides even if n is small, returning the tip of the ride. |
Rides array with one ride | The maximum earnings are simply the tip of that single ride. |
Rides array with multiple rides that are mutually exclusive (non-overlapping) | The solution should sum the tips of all the non-overlapping rides. |
Rides array with multiple rides that are all overlapping | The solution must choose the ride with the maximum tip from the overlapping set. |
Large n and a large number of rides, potentially leading to performance issues | Use dynamic programming with memoization or bottom-up iteration for optimal performance, avoiding recursion's potential stack overflow. |
Rides with zero tip | Rides with zero tip should still be considered when determining the optimal schedule since they can enable selection of other high-tip rides. |
Rides where start equals end | The solution should treat these rides as invalid and exclude them from the calculation as they consume no time but might incorrectly inflate potential earnings. |