0
0
DSA Typescriptprogramming

Activity Selection Problem in DSA Typescript

Choose your learning style9 modes available
Mental Model
Choose the most activities that don't overlap by always picking the one that finishes earliest.
Analogy: Imagine you have a single meeting room and many meetings to schedule. To fit the most meetings, always pick the meeting that ends soonest so the room becomes free quickly for the next meeting.
Activities (start, end):
[1, 4]  [3, 5]  [0, 6]  [5, 7]  [8, 9]  [5, 9]
Timeline: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9
Selected activities: [1,4] -> [5,7] -> [8,9]
Dry Run Walkthrough
Input: activities: [(1,4), (3,5), (0,6), (5,7), (8,9), (5,9)]
Goal: Select the maximum number of activities that don't overlap in time.
Step 1: Sort activities by their finish time
[(1,4), (3,5), (0,6), (5,7), (5,9), (8,9)]
Why: Sorting by finish time helps pick the earliest finishing activity first.
Step 2: Select first activity (1,4)
Selected: [(1,4)]
Why: First activity finishes earliest, so we pick it.
Step 3: Check next activity (3,5), skip because it starts before last selected ends
Selected: [(1,4)]
Why: Activity (3,5) overlaps with (1,4), so skip.
Step 4: Check next activity (0,6), skip because it overlaps
Selected: [(1,4)]
Why: Activity (0,6) overlaps with (1,4), so skip.
Step 5: Check next activity (5,7), select because it starts after last selected ends
Selected: [(1,4), (5,7)]
Why: No overlap, so select.
Step 6: Check next activity (5,9), skip because it overlaps with (5,7)
Selected: [(1,4), (5,7)]
Why: Starts at same time as (5,7), overlaps, so skip.
Step 7: Check next activity (8,9), select because it starts after last selected ends
Selected: [(1,4), (5,7), (8,9)]
Why: No overlap, so select.
Result:
Selected activities: (1,4) -> (5,7) -> (8,9)
Annotated Code
DSA Typescript
class Activity {
  constructor(public start: number, public end: number) {}
}

function activitySelection(activities: Activity[]): Activity[] {
  // Sort activities by their finish time
  activities.sort((a, b) => a.end - b.end);

  const selected: Activity[] = [];
  let lastEnd = 0;

  for (const activity of activities) {
    // Select activity if it starts after last selected ends
    if (activity.start >= lastEnd) {
      selected.push(activity);
      lastEnd = activity.end;
    }
  }

  return selected;
}

// Driver code
const activities = [
  new Activity(1, 4),
  new Activity(3, 5),
  new Activity(0, 6),
  new Activity(5, 7),
  new Activity(8, 9),
  new Activity(5, 9),
];

const result = activitySelection(activities);
for (const act of result) {
  console.log(`(${act.start},${act.end})`);
}
activities.sort((a, b) => a.end - b.end);
Sort activities by earliest finish time to prioritize.
if (activity.start >= lastEnd) {
Check if current activity starts after last selected activity ends.
selected.push(activity);
Add current activity to the selected list.
lastEnd = activity.end;
Update the end time to the current activity's end.
OutputSuccess
(1,4) (5,7) (8,9)
Complexity Analysis
Time: O(n log n) because sorting the activities by finish time dominates the runtime.
Space: O(n) because in the worst case all activities can be selected and stored.
vs Alternative: A naive approach checking all subsets would be exponential O(2^n), so this greedy method is much faster.
Edge Cases
No activities
Returns empty list, no activities selected.
DSA Typescript
for (const activity of activities) {
All activities overlap
Only one activity (the earliest finishing) is selected.
DSA Typescript
if (activity.start >= lastEnd) {
Activities with same start and end times
Selects the first one after sorting, skips others due to overlap.
DSA Typescript
if (activity.start >= lastEnd) {
When to Use This Pattern
When asked to schedule the maximum number of non-overlapping intervals or tasks, reach for the greedy Activity Selection pattern because sorting by finish time ensures optimal selection.
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 activities that overlap by checking only start times without updating last selected end time.
Fix: Always update the last selected activity's end time after selection to correctly check overlaps.
Summary
Selects the maximum number of activities that don't overlap by always choosing the earliest finishing activity next.
Use when you need to schedule the most tasks or events without conflicts in time.
The key insight is sorting by finish time lets you greedily pick the best next activity to maximize total count.