0
0
DSA Cprogramming

Activity Selection Problem in DSA C

Choose your learning style9 modes available
Mental Model
Choose the maximum number of activities that don't overlap by always picking the earliest finishing activity first.
Analogy: Imagine you have a single meeting room and many meetings to schedule. To fit the most meetings, always pick the one that ends earliest so the room becomes free sooner for the next meeting.
Activities sorted by finish time:
[Activity1]---
       [Activity2]---
           [Activity3]---
                [Activity4]---
Dry Run Walkthrough
Input: activities: [(start=1, finish=4), (start=3, finish=5), (start=0, finish=6), (start=5, finish=7), (start=8, finish=9), (start=5, finish=9)]
Goal: Select the maximum number of non-overlapping activities from the list.
Step 1: Sort activities by finish time
[(1,4), (3,5), (0,6), (5,7), (8,9), (5,9)] sorted to [(1,4), (3,5), (0,6), (5,7), (5,9), (8,9)]
Why: Sorting by finish time helps pick activities that free the room earliest.
Step 2: Select first activity (1,4)
Selected: (1,4)
Why: First activity always selected after sorting.
Step 3: Check next activity (3,5), start 3 < last finish 4, skip
Selected: (1,4)
Why: Activity overlaps with last selected, so skip.
Step 4: Check next activity (0,6), start 0 < 4, skip
Selected: (1,4)
Why: Overlaps with last selected, skip.
Step 5: Check next activity (5,7), start 5 >= 4, select
Selected: (1,4), (5,7)
Why: No overlap, select this activity.
Step 6: Check next activity (5,9), start 5 < 7, skip
Selected: (1,4), (5,7)
Why: Overlaps with last selected, skip.
Step 7: Check next activity (8,9), start 8 >= 7, select
Selected: (1,4), (5,7), (8,9)
Why: No overlap, select this activity.
Result:
Selected activities: (1,4) -> (5,7) -> (8,9) -> null
Annotated Code
DSA C
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int start;
    int finish;
} Activity;

int compare(const void *a, const void *b) {
    Activity *act1 = (Activity *)a;
    Activity *act2 = (Activity *)b;
    return act1->finish - act2->finish; // sort by finish time
}

void activitySelection(Activity activities[], int n) {
    qsort(activities, n, sizeof(Activity), compare); // sort activities by finish time
    if (n == 0) return;

    printf("Selected activities: ");
    int last_finish = activities[0].finish;
    printf("(%d,%d) ", activities[0].start, activities[0].finish); // select first activity

    for (int i = 1; i < n; i++) {
        if (activities[i].start >= last_finish) { // no overlap check
            printf("-> (%d,%d) ", activities[i].start, activities[i].finish); // select activity
            last_finish = activities[i].finish; // update last finish
        }
    }
    printf("-> null\n");
}

int main() {
    Activity activities[] = {{1,4}, {3,5}, {0,6}, {5,7}, {8,9}, {5,9}};
    int n = sizeof(activities) / sizeof(activities[0]);
    activitySelection(activities, n);
    return 0;
}
qsort(activities, n, sizeof(Activity), compare);
sort activities by finish time to prioritize earliest finishing
printf("(%d,%d) ", activities[0].start, activities[0].finish);
select first activity after sorting
if (activities[i].start >= last_finish) {
check if current activity starts after or when last selected finished
printf("-> (%d,%d) ", activities[i].start, activities[i].finish);
select current activity if no overlap
last_finish = activities[i].finish;
update last finish time to current activity's finish
OutputSuccess
Selected activities: (1,4) -> (5,7) -> (8,9) -> null
Complexity Analysis
Time: O(n log n) because sorting the activities by finish time dominates the runtime
Space: O(1) because selection is done in place with no extra data structures
vs Alternative: Naive approach tries all subsets with exponential time; greedy sorting reduces it to O(n log n)
Edge Cases
No activities
No output, no activities selected
DSA C
qsort(activities, n, sizeof(Activity), compare);
All activities overlap
Only the first activity is selected
DSA C
if (activities[i].start >= last_finish) {
Activities with same finish time
Selects the first one and skips others starting before last finish
DSA C
if (activities[i].start >= last_finish) {
When to Use This Pattern
When asked to schedule the maximum number of non-overlapping intervals, use the greedy activity selection pattern by sorting on finish times.
Common Mistakes
Mistake: Sorting activities by start time instead of finish time
Fix: Sort activities by their finish time to ensure earliest finishing activities are chosen first
Mistake: Selecting overlapping activities by not checking start >= last finish
Fix: Always check if current activity starts after or at the finish time of last selected activity
Summary
Selects the maximum number of non-overlapping activities by always choosing the earliest finishing one.
Use when you need to schedule the most tasks or events without overlap in a single resource.
Sorting by finish time and greedily picking compatible activities ensures optimal selection.