You are given a 0-indexed 2D integer array of events where events[i] = [startTimei, endTimei, valuei]. The ith event starts at startTimei and ends at endTimei, and if you attend this event, you will receive a value of valuei. You can choose at most two non-overlapping events to attend such that the sum of their values is maximized.
Return this maximum sum.
Note that the start time and end time is inclusive: that is, you cannot attend two events where one of them starts and the other ends at the same time. More specifically, if you attend an event with end time t, the next event must start at or after t + 1.
Example 1:
Input: events = [[1,3,2],[4,5,2],[2,4,3]] Output: 4 Explanation: Choose the green events, 0 and 1 for a sum of 2 + 2 = 4.
Example 2:
Input: events = [[1,3,2],[4,5,2],[1,5,5]] Output: 5 Explanation: Choose event 2 for a sum of 5.
Example 3:
Input: events = [[1,5,3],[1,5,1],[6,6,5]] Output: 8 Explanation: Choose events 0 and 2 for a sum of 3 + 5 = 8.
Constraints:
2 <= events.length <= 105events[i].length == 31 <= startTimei <= endTimei <= 1091 <= valuei <= 106When 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:
We're trying to find the two best events that don't happen at the same time. The brute force approach involves checking every possible pair of events to see if they overlap, and if they don't, adding up their values to see which pair gives us the highest combined value.
Here's how the algorithm would work step-by-step:
def max_two_non_overlapping_events_brute_force(events):
max_combined_value = 0
for first_event_index in range(len(events)):
for second_event_index in range(len(events)):
# Avoid comparing the same event with itself
if first_event_index == second_event_index:
continue
first_event_start_time = events[first_event_index][0]
first_event_end_time = events[first_event_index][1]
first_event_value = events[first_event_index][2]
second_event_start_time = events[second_event_index][0]
second_event_end_time = events[second_event_index][1]
second_event_value = events[second_event_index][2]
# Check if the events overlap
if not (first_event_end_time <= second_event_start_time or \
second_event_end_time <= first_event_start_time):
continue
# Found two non-overlapping events
combined_value = first_event_value + second_event_value
# Update the maximum value
max_combined_value = max(max_combined_value, combined_value)
return max_combined_valueTo find the two best non-overlapping events, we want to avoid checking every single pair. The efficient strategy involves pre-calculating the best possible event score up to any given point and then using this information to quickly find the best non-overlapping pair.
Here's how the algorithm would work step-by-step:
def two_best_non_overlapping_events(events):
# Sort events based on end times.
events.sort(key=lambda event: event[1])
max_value_at_time = {}
best_value_so_far = 0
# Precompute the maximum event value up to each end time.
for start_time, end_time, event_value in events:
best_value_so_far = max(best_value_so_far, event_value)
max_value_at_time[end_time] = best_value_so_far
max_two_events_value = 0
for start_time, end_time, event_value in events:
# Find the best non-overlapping event before the current event.
best_previous_event_value = 0
for previous_end_time in max_value_at_time:
if previous_end_time <= start_time:
best_previous_event_value = max(best_previous_event_value, max_value_at_time[previous_end_time])
# Update the maximum value of two non-overlapping events.
current_two_events_value = event_value + best_previous_event_value
max_two_events_value = max(max_two_events_value, current_two_events_value)
# Return the maximum value of two non-overlapping events.
return max_two_events_value| Case | How to Handle |
|---|---|
| Empty events array | Return 0 or an appropriate default value, indicating no events can be selected. |
| Events array with only one event | Return the value of the single event since there is nothing to compare it to for overlaps. |
| All events overlap with each other | Return the maximum value of a single event since no two non-overlapping events exist. |
| Very large event values leading to potential integer overflow | Use a data type with sufficient range (e.g., long) to store intermediate sums. |
| Events sorted in reverse order of start time | The algorithm should correctly handle reverse-sorted input without relying on any pre-sorted assumptions. |
| Maximum size array | Ensure algorithm scales to handle max input size by using efficient algorithms like dynamic programming or binary search where needed to avoid excessive computation. |
| Events with identical start and end times but different values | The algorithm needs to correctly iterate and consider all possible event values for optimal selection despite the duplicated start/end times. |
| Events with very close start and end times causing floating point precision issues if used | The algorithm should rely on integers and discrete comparison for event times, avoiding floating point math for these properties entirely. |