3635. Earliest Finish Time for Land and Water Rides II
Problem Description
You are given two categories of theme park attractions: land rides and water rides.
-
Land rides
landStartTime[i]
: the earliest time thei
th land ride can be boarded.landDuration[i]
: how long thei
th land ride lasts.
-
Water rides
waterStartTime[j]
: the earliest time thej
th water ride can be boarded.waterDuration[j]
: how long thej
th water ride lasts.
A tourist must experience exactly one ride from each category, in either order.
- A ride may be started at its opening time or any later moment.
- If a ride is started at time
t
, it finishes at timet + duration
. - Immediately after finishing one ride, the tourist may board the other (if it is already open) or wait until it opens.
Return the earliest possible time at which the tourist can finish both rides.
Intuition
The goal is to finish one ride from each category as early as possible. Since either ride can be taken first, it's best to try both orders: doing a land ride first then a water ride, and vice versa.
For each order, consider which option gets us off the first ride earliest. This means picking the land (or water) ride where start time + duration
is smallest. Then, start the second ride as soon as the first is done, or as soon as its opening time allows, whichever is later. The total finishing time will be that ride’s actual start time plus its duration.
By checking all options in both orders and picking the smallest possible finishing time, we make sure the tourist spends the least possible total time.
Solution Approach
The problem is solved by considering both possible sequences for riding: land ride first, then water ride; or water ride first, then land ride.
For each sequence:
-
Find the earliest finish for the first ride category: For example, for land rides, calculate
landStartTime[i] + landDuration[i]
for all rides and pick the minimum. This means finishing the land ride as early as possible. -
For each ride in the second category, calculate the earliest possible finish time: For each water ride, compute the earliest time to start it:
- It's either its own opening time or the time the first ride finishes, whichever is later:
max(waterStartTime[j], min_land_end)
. - Its finish time is then
max(waterStartTime[j], min_land_end) + waterDuration[j]
.
- It's either its own opening time or the time the first ride finishes, whichever is later:
-
Pick the overall earliest finish time from all rides in the second category.
-
Repeat the process with the sequence reversed (water ride first, then land ride).
-
The final answer is the minimum finish time found in both sequences.
The code uses a helper function calc(a1, t1, a2, t2)
that implements these steps:
- It first computes
min_end = min(a + t for a, t in zip(a1, t1))
, the earliest finish for the first ride type. - For each ride in the second category, it computes
max(a, min_end) + t
and returns the minimum.
This is repeated for both ride orders, and the minimum of both results is returned as the answer.
This approach ensures all possible combinations are considered efficiently since it doesn't require checking every pair, but always picks the optimal ride in each step.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Suppose there are the following rides:
-
Land rides:
- Ride 0: opens at 2, lasts 5 ⇒ finishes at 7
- Ride 1: opens at 8, lasts 3 ⇒ finishes at 11
-
Water rides:
- Ride 0: opens at 4, lasts 4 ⇒ finishes at 8
- Ride 1: opens at 6, lasts 2 ⇒ finishes at 8
Let's walk through both possible ride orders to find the earliest finish time.
1. Land ride first, then water ride
Step 1: Find the land ride with the earliest finish.
- Ride 0: 2 + 5 = 7
- Ride 1: 8 + 3 = 11 So, earliest finish = 7 (from land ride 0).
Step 2: Try all water rides, starting each after land finishes (or after their own opening).
- Water 0: can start at max(4, 7) = 7, finishes at 7 + 4 = 11
- Water 1: can start at max(6, 7) = 7, finishes at 7 + 2 = 9
Earliest possible finish in this order: 9 (land 0 → water 1).
2. Water ride first, then land ride
Step 1: Find the water ride with the earliest finish.
- Water 0: 4 + 4 = 8
- Water 1: 6 + 2 = 8
Earliest finish = 8 (either water ride).
Step 2: Try all land rides, starting each after water finishes (or after their own opening).
- Land 0: can start at max(2, 8) = 8, finishes at 8 + 5 = 13
- Land 1: can start at max(8, 8) = 8, finishes at 8 + 3 = 11
Earliest possible finish in this order: 11 (water → land 1).
Final Answer
Compare both orders: minimum of 9 and 11. Earliest finish time is 9, by taking land ride 0 first and then water ride 1.
Solution Implementation
1from typing import List
2
3class Solution:
4 def earliestFinishTime(
5 self,
6 landStartTime: List[int],
7 landDuration: List[int],
8 waterStartTime: List[int],
9 waterDuration: List[int],
10 ) -> int:
11 # Helper function to compute the earliest possible finish time
12 # if we do type1 task, then type2 task.
13 def calc(type1_start, type1_dur, type2_start, type2_dur):
14 # The earliest finish time of any type1 task.
15 earliest_type1_end = min(start + dur for start, dur in zip(type1_start, type1_dur))
16 # For each type2 task, compute when it can start: it can't start before both its available time and after the earliest type1 finished.
17 # Return the earliest finish time after finishing the type2 task.
18 return min(max(start, earliest_type1_end) + dur for start, dur in zip(type2_start, type2_dur))
19
20 # Two perspectives:
21 # 1. Land first, then water (earliest possible finish time).
22 finish_time_land_first = calc(landStartTime, landDuration, waterStartTime, waterDuration)
23 # 2. Water first, then land.
24 finish_time_water_first = calc(waterStartTime, waterDuration, landStartTime, landDuration)
25 # Return the minimum possible finish time.
26 return min(finish_time_land_first, finish_time_water_first)
27
1class Solution {
2 /**
3 * Calculates the earliest time all land and water tasks can be finished,
4 * considering both orders: land-then-water and water-then-land
5 *
6 * @param landStartTime Array of start times for land tasks
7 * @param landDuration Array of durations for land tasks
8 * @param waterStartTime Array of start times for water tasks
9 * @param waterDuration Array of durations for water tasks
10 * @return The earliest finish time by considering both task orders
11 */
12 public int earliestFinishTime(
13 int[] landStartTime, int[] landDuration, int[] waterStartTime, int[] waterDuration) {
14 // Calculate finish time: finish all land first, then water
15 int finishLandFirst = calc(landStartTime, landDuration, waterStartTime, waterDuration);
16 // Calculate finish time: finish all water first, then land
17 int finishWaterFirst = calc(waterStartTime, waterDuration, landStartTime, landDuration);
18 // Return the minimum of the two approaches
19 return Math.min(finishLandFirst, finishWaterFirst);
20 }
21
22 /**
23 * Helper method to compute the finish time for one order of tasks.
24 * For (firstStart, firstDur, secondStart, secondDur), this finds the earliest
25 * time all first-tasks can finish, then schedules each second-task after that.
26 *
27 * @param firstStart Array of start times for first group of tasks
28 * @param firstDur Array of durations for first group of tasks
29 * @param secondStart Array of start times for second group of tasks
30 * @param secondDur Array of durations for second group of tasks
31 * @return The earliest finish time for this schedule order
32 */
33 private int calc(int[] firstStart, int[] firstDur, int[] secondStart, int[] secondDur) {
34 // Find the finishing time after all first group tasks are done
35 int minEndFirst = Integer.MAX_VALUE;
36 for (int i = 0; i < firstStart.length; ++i) {
37 // Completion time for each first-group task
38 minEndFirst = Math.min(minEndFirst, firstStart[i] + firstDur[i]);
39 }
40
41 // Determine the minimum finish time for second group tasks
42 int minFinish = Integer.MAX_VALUE;
43 for (int i = 0; i < secondStart.length; ++i) {
44 // Start the second-group task when both groups are ready, and add its duration
45 int start = Math.max(minEndFirst, secondStart[i]);
46 minFinish = Math.min(minFinish, start + secondDur[i]);
47 }
48 return minFinish;
49 }
50}
51
1#include <vector>
2#include <climits>
3#include <algorithm>
4using namespace std;
5
6class Solution {
7public:
8 // Returns the minimal finish time by trying both possible orders:
9 // (1) Do all land tasks first, then water tasks.
10 // (2) Do all water tasks first, then land tasks.
11 int earliestFinishTime(vector<int>& landStartTime, vector<int>& landDuration, vector<int>& waterStartTime, vector<int>& waterDuration) {
12 // Try both orders and return the minimum finish time
13 int finishTimeByLandFirst = calc(landStartTime, landDuration, waterStartTime, waterDuration);
14 int finishTimeByWaterFirst = calc(waterStartTime, waterDuration, landStartTime, landDuration);
15 return min(finishTimeByLandFirst, finishTimeByWaterFirst);
16 }
17
18 // Calculates the earliest finish time if group1 tasks are done first, then group2 tasks.
19 int calc(vector<int>& group1Start, vector<int>& group1Duration,
20 vector<int>& group2Start, vector<int>& group2Duration) {
21 // Find the time when the last group1 task finishes.
22 int group1Finish = INT_MAX;
23 for (int i = 0; i < group1Start.size(); ++i) {
24 group1Finish = min(group1Finish, group1Start[i] + group1Duration[i]);
25 }
26 // For each group2 task, compute the earliest it can start (after group1 is done) and finish.
27 int minTotalFinish = INT_MAX;
28 for (int i = 0; i < group2Start.size(); ++i) {
29 int group2ActualStart = max(group1Finish, group2Start[i]);
30 int group2Finish = group2ActualStart + group2Duration[i];
31 minTotalFinish = min(minTotalFinish, group2Finish);
32 }
33 return minTotalFinish;
34 }
35};
36
1/**
2 * Calculates the earliest finish time by considering starting on land first or water first.
3 * Evaluates both routes and returns the minimal possible finish time.
4 *
5 * @param landStartTime - Array of start times for land segments.
6 * @param landDuration - Array of durations for land segments.
7 * @param waterStartTime - Array of start times for water segments.
8 * @param waterDuration - Array of durations for water segments.
9 * @returns The earliest finish time possible by alternating land and water sequences.
10 */
11function earliestFinishTime(
12 landStartTime: number[],
13 landDuration: number[],
14 waterStartTime: number[],
15 waterDuration: number[],
16): number {
17 // Try starting with land, then water
18 const finishWithLandFirst = calc(landStartTime, landDuration, waterStartTime, waterDuration);
19 // Try starting with water, then land
20 const finishWithWaterFirst = calc(waterStartTime, waterDuration, landStartTime, landDuration);
21 // Return the minimal finish among the two alternatives
22 return Math.min(finishWithLandFirst, finishWithWaterFirst);
23}
24
25/**
26 * Helper function to calculate finish time for a particular order of activities.
27 *
28 * @param firstStart - Array of start times for the first set of segments (either land or water).
29 * @param firstDuration - Array of durations for the first set of segments.
30 * @param secondStart - Array of start times for the second set of segments.
31 * @param secondDuration - Array of durations for the second set of segments.
32 * @returns The earliest possible finish time for the given order.
33 */
34function calc(
35 firstStart: number[],
36 firstDuration: number[],
37 secondStart: number[],
38 secondDuration: number[]
39): number {
40 // Find the earliest possible end time after finishing all "first" segments
41 let minFirstEnd = Number.MAX_SAFE_INTEGER;
42 for (let i = 0; i < firstStart.length; i++) {
43 minFirstEnd = Math.min(minFirstEnd, firstStart[i] + firstDuration[i]);
44 }
45 // Try all second segments as possible next activities
46 let minTotalEnd = Number.MAX_SAFE_INTEGER;
47 for (let i = 0; i < secondStart.length; i++) {
48 // Start second segment after finishing first, but cannot start before its own available time
49 const secondStartTime = Math.max(minFirstEnd, secondStart[i]);
50 minTotalEnd = Math.min(minTotalEnd, secondStartTime + secondDuration[i]);
51 }
52 // Return the minimal overall finish time
53 return minTotalEnd;
54}
55
Time and Space Complexity
The time complexity of the code is O(n)
, where n
is the length of the ride lists (assuming all input lists are of the same length). This is because each call to the calc
function involves iterating through entire lists twice with a pair of zip
and min
/max
/sum
operations, each being O(n)
. The total time over both calls remains O(n)
.
The space complexity is O(1)
because no additional data structures are created that grow with the input size; only variables for intermediate computations are used.
What does the following code do?
1def f(arr1, arr2):
2 i, j = 0, 0
3 new_arr = []
4 while i < len(arr1) and j < len(arr2):
5 if arr1[i] < arr2[j]:
6 new_arr.append(arr1[i])
7 i += 1
8 else:
9 new_arr.append(arr2[j])
10 j += 1
11 new_arr.extend(arr1[i:])
12 new_arr.extend(arr2[j:])
13 return new_arr
14
1public static List<Integer> f(int[] arr1, int[] arr2) {
2 int i = 0, j = 0;
3 List<Integer> newArr = new ArrayList<>();
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.add(arr1[i]);
8 i++;
9 } else {
10 newArr.add(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.add(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.add(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
1function f(arr1, arr2) {
2 let i = 0, j = 0;
3 let newArr = [];
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.push(arr1[i]);
8 i++;
9 } else {
10 newArr.push(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.push(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.push(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!