You are given an array of events
where events[i] = [startDayi, endDayi]
. Every event i
starts at startDayi
and ends at endDayi
.
You can attend an event i
at any day d
where startDayi <= d <= endDayi
. You can only attend one event at any time d
.
Return the maximum number of events you can attend.
Example 1:
Input: events = [[1,2],[2,3],[3,4]] Output: 3 Explanation: You can attend all the three events. One way to attend them all is as shown. Attend the first event on day 1. Attend the second event on day 2. Attend the third event on day 3.
Example 2:
Input: events= [[1,2],[2,3],[3,4],[1,2]] Output: 4
Constraints:
1 <= events.length <= 105
events[i].length == 2
1 <= startDayi <= endDayi <= 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 goal is to attend the maximum number of events given a list of events with start and end days. The brute force method involves exploring every possible combination of events, attending some and skipping others, to find the best possible schedule. It's like trying out every single choice until you find one that works best.
Here's how the algorithm would work step-by-step:
def max_events_brute_force(events):
max_attended_events = 0
def solve(index, attended_events, busy_days):
nonlocal max_attended_events
if index == len(events):
max_attended_events = max(max_attended_events, len(attended_events))
return
# Option 1: Skip the current event
solve(index + 1, attended_events, busy_days)
# Option 2: Attend the current event if possible
start_day = events[index][0]
end_day = events[index][1]
can_attend = True
for day in range(start_day, end_day + 1):
if day in busy_days:
can_attend = False
break
# Only proceed if the event doesn't overlap with busy days
if can_attend:
# Create a copy to avoid modifying the original list.
new_busy_days = busy_days.copy()
# Mark days as busy if attending this event
for day in range(start_day, end_day + 1):
new_busy_days.add(day)
# Because we attended one more event we can add the new one
solve(index + 1, attended_events + [index], new_busy_days)
solve(0, [], set())
return max_attended_events
To maximize the number of events you can attend, focus on picking the events that end sooner rather than later. This frees up more time to attend other events. We'll use a method that prioritizes ending earlier while making sure we don't try to attend events that overlap in time.
Here's how the algorithm would work step-by-step:
def max_events_to_attend(events):
events.sort(key=lambda x: x[1])
attended_days = set()
number_of_events_attended = 0
# Iterate through events sorted by end date
for start_day, end_day in events:
for day in range(start_day, end_day + 1):
# Check if the current day hasn't been attended yet
if day not in attended_days:
attended_days.add(day)
# Increment event count if attended
number_of_events_attended += 1
break
return number_of_events_attended
def max_events_to_attend_optimal(events):
# Sort events by end date to prioritize earlier ending events.
events.sort(key=lambda x: x[1])
attended_days = set()
max_events = 0
for start_day, end_day in events:
# Attempt to attend the event on the earliest possible day.
for day in range(start_day, end_day + 1):
# Attend if the day is available.
if day not in attended_days:
attended_days.add(day)
max_events += 1
break
return max_events
def max_events(events):
# Sort the events based on their end dates.
events.sort(key=lambda x: x[1])
attended_events = []
# Iterate through each event in the sorted list.
for event_start, event_end in events:
can_attend = True
# Check for overlaps with already attended events.
for attended_start, attended_end in attended_events:
if event_start <= attended_end and event_end >= attended_start:
can_attend = False
break
# Add the event to the attended list if no overlap.
if can_attend:
attended_events.append((event_start, event_end))
# Return the total number of events attended.
return len(attended_events)
def max_events_attend(events):
# Sort events based on their end day
events.sort(key=lambda x: x[1])
attended_days = set()
event_count = 0
# Iterate through sorted events
for start_day, end_day in events:
# Attempt to find a suitable day within the event's duration
for day in range(start_day, end_day + 1):
# If the day is not already attended, attend the event
if day not in attended_days:
# Mark the day as attended
attended_days.add(day)
event_count += 1
break
return event_count
def max_number_of_events(events):
# Sort events by end date, prioritizing events finishing sooner.
events.sort(key=lambda x: x[1])
attended_days = set()
max_possible_events = 0
# Iterate through each event.
for start_date, end_date in events:
# Attempt to attend the event on the earliest possible day.
for day in range(start_date, end_date + 1):
# Check if the current day is available.
if day not in attended_days:
# Mark the day as attended.
attended_days.add(day)
# Increment the number of attended events.
max_possible_events += 1
break
return max_possible_events
def max_events_that_can_be_attended(events):
# Sort events by end date
events.sort(key=lambda x: x[1])
attended_dates = set()
event_counter = 0
# Iterate over events in sorted order
for start_date, end_date in events:
# Try to attend event on each day between start and end date
for date in range(start_date, end_date + 1):
# Attend the event if the date isn't taken
if date not in attended_dates:
attended_dates.add(date)
event_counter += 1
break
return event_counter
Case | How to Handle |
---|---|
Empty event list | Return 0 immediately as no events can be attended. |
Events with start day equal to end day | Treat these as valid single-day events. |
Overlapping events | The algorithm needs to prioritize events to maximize attendance, for example using a greedy approach of selecting events that end earliest. |
Large number of events (scalability) | Use efficient data structures and algorithms (e.g., priority queue and sorting) to avoid time complexity issues, ideally O(n log n). |
Events with large start and end day values (integer overflow) | Ensure that the data type used for start and end days is large enough to accommodate all possible values, potentially using 64-bit integers if necessary. |
Events with identical start and end days | The algorithm should handle duplicate events correctly as separate opportunities to attend an event on that day. |
Events that span a very long duration | The algorithm should consider events with a very large duration, like from day 1 to day 10000, and the data structure (e.g., priority queue) should handle it effectively. |
All events occur on the same day | The maximum number of events that can be attended is 1. |