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
0 2 4 6 8 A0 Activity 0 A1 Activity 1 A2 Activity 2 A3 Activity 3 A4 Activity 4 Selected Not Selected

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.

Updated on: 2026-03-25T06:48:20+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements