Maximum Earnings From Taxi
MEDIUMDescription
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 <= 1051 <= rides.length <= 3 * 104rides[i].length == 31 <= starti < endi <= n1 <= tipi <= 105
Approaches
Checkout 3 different approaches to solve Maximum Earnings From Taxi. Click on different approaches to view the approach and algorithm in detail.
Dynamic Programming on Points
This is the most efficient approach for the given constraints. It uses dynamic programming where the state is tied to the points on the road. We build a dp array where dp[i] stores the maximum earnings we can have by the time we reach point i. The solution is built iteratively by considering the maximum earnings from the previous point and the potential earnings from any rides that drop off a passenger at the current point.
Algorithm
- Preprocessing: Group the rides by their
endpoint. AHashMap<Integer, List<int[]>>is an effective way to do this, mapping eachendpoint to a list of rides that finish there. - DP Initialization: Create a
dparray of sizen + 1.dp[i]will represent the maximum earnings achievable up to pointion the road. Initialize alldpvalues to 0. - DP Iteration: Iterate from
i = 1ton.- For each point
i, we have two main possibilities to determinedp[i]:- No ride ends at
i: In this case, we just drove from pointi-1toiwithout a passenger. The maximum earnings are the same as the earnings up to pointi-1. So, we setdp[i] = dp[i-1]. - One or more rides end at
i: For each ride[start, end, tip]whereend == i, we calculate a potential new maximum earning. This would be the earnings from this ride (end - start + tip) plus the maximum earnings we had accumulated up to thestartpoint of this ride (dp[start]).
- No ride ends at
- We update
dp[i]to be the maximum ofdp[i-1]and all potential earnings calculated from rides ending ati.
- For each point
- Result: The final answer is the value stored in
dp[n], which represents the maximum earnings after reaching the final destination.
This dynamic programming approach defines its state based on the location on the road. We let dp[i] be the maximum possible earnings after arriving at point i. Our goal is to compute dp[n].
The transition for dp[i] is based on what happens at point i. To arrive at point i, we could have either driven from i-1 without a passenger, or we could have just completed a ride that ended at i.
- Base case:
dp[0] = 0. No earnings before starting. - Transition: For each point
ifrom 1 ton:- The default maximum earning is inherited from the previous point:
dp[i] = dp[i-1]. - We then check if any rides end at point
i. To do this efficiently, we first preprocess theridesinto a map where keys are end points. For every ride[start, end, tip]withend == i, we calculate a potential new maximum earning:dp[start] + (end - start + tip). This represents the earnings from an optimal path tostart, followed by taking this specific ride. - We update
dp[i]with the maximum value found amongdp[i-1]and all possibilities from rides ending ati.
- The default maximum earning is inherited from the previous point:
This ensures that at each point i, dp[i] holds the optimal earnings. The final answer is dp[n].
import java.util.*;
class Solution {
public long maxTaxiEarnings(int n, int[][] rides) {
// Group rides by their end point for efficient lookup.
// The map stores: endPoint -> List of {startPoint, tip}
Map<Integer, List<int[]>> ridesByEnd = new HashMap<>();
for (int[] ride : rides) {
ridesByEnd.computeIfAbsent(ride[1], k -> new ArrayList<>()).add(new int[]{ride[0], ride[2]});
}
// dp[i] will store the maximum earnings up to point i.
long[] dp = new long[n + 1];
for (int i = 1; i <= n; i++) {
// Option 1: Don't end a ride at point i. Earnings are same as up to i-1.
dp[i] = dp[i - 1];
// Option 2: Check if any rides end at point i.
if (ridesByEnd.containsKey(i)) {
for (int[] rideInfo : ridesByEnd.get(i)) {
int start = rideInfo[0];
int tip = rideInfo[1];
long profit = (long)i - start + tip;
// Compare with current max and update if this path is better.
dp[i] = Math.max(dp[i], dp[start] + profit);
}
}
}
return dp[n];
}
}
Complexity Analysis
Pros and Cons
- Most efficient time complexity for the given constraints.
- The DP state and transition directly model the problem's progression along the road, making it intuitive.
- The space complexity is O(n + R), which can be large if
nis very large.
Code Solutions
Checking out 3 solutions in different languages for Maximum Earnings From Taxi. Click on different languages to view the code.
class Solution { private int m ; private int [][] rides ; private Long [] f ; public long maxTaxiEarnings ( int n , int [][] rides ) { Arrays . sort ( rides , ( a , b ) -> a [ 0 ] - b [ 0 ]); m = rides . length ; f = new Long [ m ]; this . rides = rides ; return dfs ( 0 ); } private long dfs ( int i ) { if ( i >= m ) { return 0 ; } if ( f [ i ] != null ) { return f [ i ]; } int [] r = rides [ i ]; int st = r [ 0 ], ed = r [ 1 ], tip = r [ 2 ]; int j = search ( ed , i + 1 ); return f [ i ] = Math . max ( dfs ( i + 1 ), dfs ( j ) + ed - st + tip ); } private int search ( int x , int l ) { int r = m ; while ( l < r ) { int mid = ( l + r ) >> 1 ; if ( rides [ mid ][ 0 ] >= x ) { r = mid ; } else { l = mid + 1 ; } } return l ; } }Video Solution
Watch the video walkthrough for Maximum Earnings From Taxi
Similar Questions
5 related questions you might find useful
Algorithms:
Patterns:
Data Structures:
Companies:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.