Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Python Program for Activity Selection Problem
The activity selection problem selects the maximum number of non-overlapping activities from a given set. Each activity has a start and finish time, and a single person can perform only one activity at a time.
Problem Statement
You are given n activities, each defined by a start time and a finish time. The goal is to choose the maximum number of activities that a single person can perform without any overlap between the selected activities.
Variable Notations
Below are the variables used in the problem definition ?
- N: Total number of activities
- S: An array of start times
- F: An array of finish times
Greedy Strategy
To solve this problem, we use a greedy strategy where we always pick the next activity that finishes the earliest and does not overlap with the previously selected ones. This approach ensures the maximum number of activities are chosen.
Steps
The greedy solution follows these steps to select non-overlapping activities ?
- Sort the activities based on their finish times
- Select the first activity from the sorted list
- For the remaining activities, choose an activity if its start time is equal to or greater than the finish time of the last selected activity
Python Implementation
In this example, we first sort the activities based on finish times. We then select the first activity and continue checking subsequent ones to include only non-overlapping ones ?
# Function to select maximum number of non-overlapping activities
def activity_selection(start, finish):
n = len(start)
print("The selected activities are:")
# First activity is always selected
i = 0
print(f"Activity {i}: ({start[i]}, {finish[i]})")
# Consider rest of the activities
for j in range(1, n):
if start[j] >= finish[i]:
print(f"Activity {j}: ({start[j]}, {finish[j]})")
i = j
# Start and finish times
start = [1, 2, 0, 3, 2, 4]
finish = [2, 5, 4, 6, 8, 8]
print("Original activities:")
for i in range(len(start)):
print(f"Activity {i}: Start={start[i]}, Finish={finish[i]}")
# Sort activities based on finish time
activities = sorted(zip(start, finish), key=lambda x: x[1])
start_sorted, finish_sorted = zip(*activities)
print("\nAfter sorting by finish time:")
for i in range(len(start_sorted)):
print(f"Activity {i}: Start={start_sorted[i]}, Finish={finish_sorted[i]}")
print("\nSelection process:")
# Run the selection
activity_selection(start_sorted, finish_sorted)
The output of the above code is ?
Original activities: Activity 0: Start=1, Finish=2 Activity 1: Start=2, Finish=5 Activity 2: Start=0, Finish=4 Activity 3: Start=3, Finish=6 Activity 4: Start=2, Finish=8 Activity 5: Start=4, Finish=8 After sorting by finish time: Activity 0: Start=1, Finish=2 Activity 1: Start=0, Finish=4 Activity 2: Start=2, Finish=5 Activity 3: Start=3, Finish=6 Activity 4: Start=2, Finish=8 Activity 5: Start=4, Finish=8 Selection process: The selected activities are: Activity 0: (1, 2) Activity 3: (3, 6)
Optimized Version with Activity Details
Here's an enhanced version that returns the actual selected activities with their details ?
def activity_selection_detailed(activities):
# Sort activities by finish time
activities.sort(key=lambda x: x[2])
selected = []
last_finish_time = 0
for activity in activities:
name, start, finish = activity
if start >= last_finish_time:
selected.append(activity)
last_finish_time = finish
return selected
# Define activities: (name, start_time, finish_time)
activities = [
("Meeting", 1, 2),
("Lunch", 2, 5),
("Training", 0, 4),
("Workshop", 3, 6),
("Conference", 2, 8),
("Review", 4, 8)
]
print("Available activities:")
for name, start, finish in activities:
print(f"{name}: {start} to {finish}")
selected_activities = activity_selection_detailed(activities)
print(f"\nMaximum {len(selected_activities)} activities can be selected:")
for name, start, finish in selected_activities:
print(f"{name}: {start} to {finish}")
The output of the above code is ?
Available activities: Meeting: 1 to 2 Lunch: 2 to 5 Training: 0 to 4 Workshop: 3 to 6 Conference: 2 to 8 Review: 4 to 8 Maximum 2 activities can be selected: Meeting: 1 to 2 Workshop: 3 to 6
Time Complexity
The time complexity of the greedy activity selection algorithm is O(n log n) due to the sorting step. The selection process itself takes O(n) time.
Conclusion
The activity selection problem demonstrates the power of greedy algorithms. By sorting activities by finish time and selecting non-overlapping ones, we achieve an optimal solution with O(n log n) complexity.
