Activity Selection Problem in DSA Typescript - Time & Space Complexity
We want to know how the time needed to select activities grows as the number of activities increases.
How does the algorithm's work change when we have more activities to choose from?
Analyze the time complexity of the following code snippet.
function activitySelection(start: number[], finish: number[]): number[] {
const n = start.length;
const selected: number[] = [];
let lastFinish = 0;
for (let i = 0; i < n; i++) {
if (start[i] >= lastFinish) {
selected.push(i);
lastFinish = finish[i];
}
}
return selected;
}
This code picks the maximum number of activities that don't overlap, assuming activities are sorted by finish time.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: A single loop that goes through all activities once.
- How many times: Exactly once for each activity, so n times.
As the number of activities grows, the work grows in a straight line.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks |
| 100 | About 100 checks |
| 1000 | About 1000 checks |
Pattern observation: The number of operations grows directly with the number of activities.
Time Complexity: O(n)
This means the time to select activities grows in direct proportion to how many activities there are.
[X] Wrong: "The algorithm checks every pair of activities, so it must be quadratic."
[OK] Correct: The code only loops once through the list, not nested loops, so it does not compare every pair.
Understanding this linear time solution shows you can spot efficient ways to handle scheduling problems, a useful skill in many coding challenges.
"What if the activities were not sorted by finish time? How would the time complexity change?"
Practice
Activity Selection Problem?Solution
Step 1: Understand the problem goal
The Activity Selection Problem aims to choose activities that do not overlap and maximize the count.Step 2: Identify the correct objective
Among the options, only selecting the maximum number of non-overlapping activities matches the problem's goal.Final Answer:
Select the maximum number of activities that don't overlap in time -> Option AQuick Check:
Goal = Max non-overlapping activities [OK]
- Confusing longest duration with maximum count
- Sorting by start time only
- Summing all activity durations
Solution
Step 1: Identify sorting criteria for Activity Selection
Activities must be sorted by their finish times in ascending order to apply the greedy approach.Step 2: Match sorting code to criteria
activities.sort((a, b) => a.finish - b.finish); sorts activities by finish time ascending, which is correct for the problem.Final Answer:
activities.sort((a, b) => a.finish - b.finish); -> Option AQuick Check:
Sort by finish time ascending [OK]
- Sorting by start time instead of finish time
- Sorting finish time descending
- Using incorrect comparison operators
const 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}
];
activities.sort((a, b) => a.finish - b.finish);
const selected = [];
let lastFinish = 0;
for (const activity of activities) {
if (activity.start >= lastFinish) {
selected.push(activity);
lastFinish = activity.finish;
}
}
console.log(selected);Solution
Step 1: Sort activities by finish time
Sorted list: [{1,4}, {3,5}, {0,6}, {5,7}, {8,9}, {5,9}]Step 2: Select activities greedily
Select {1,4} (start 1 >= 0), then {5,7} (start 5 >= 4), then {8,9} (start 8 >= 7). Others overlap.Final Answer:
[{start:1, finish:4}, {start:5, finish:7}, {start:8, finish:9}] -> Option CQuick Check:
Greedy selection = chosen activities [OK]
- Selecting overlapping activities
- Not sorting by finish time
- Updating lastFinish incorrectly
const activities = [
{start: 1, finish: 3},
{start: 2, finish: 5},
{start: 4, finish: 7}
];
activities.sort((a, b) => a.start - b.start);
const selected = [];
let lastFinish = 0;
for (const activity of activities) {
if (activity.start >= lastFinish) {
selected.push(activity);
lastFinish = activity.finish;
}
}
console.log(selected);Solution
Step 1: Check sorting criteria
The code sorts activities by start time, but the greedy algorithm requires sorting by finish time.Step 2: Identify impact of sorting error
Sorting by start time can cause incorrect selection of overlapping activities, breaking the algorithm.Final Answer:
Sorting by start time instead of finish time -> Option BQuick Check:
Sort by finish time needed [OK]
- Sorting by start time
- Confusing variable declarations
- Wrong if condition operators
const activities = [
{start: 0, finish: 3},
{start: 1, finish: 4},
{start: 3, finish: 5},
{start: 4, finish: 7},
{start: 5, finish: 9},
{start: 8, finish: 10}
];How many activities can be selected using the Activity Selection Problem's greedy approach, and which are they?
Solution
Step 1: Sort activities by finish time
Sorted: [{0,3}, {1,4}, {3,5}, {4,7}, {5,9}, {8,10}]Step 2: Select greedily
{0,3} (last=3); skip {1,4}; {3,5} (last=5); {4,7} overlaps with {3,5} so skip; {5,9} (last=9); {8,10} overlaps with {5,9} so skip. Actually, {8,10} starts before 9, so overlaps. So selected are {0,3}, {3,5}, {5,9} only 3 activities.Final Answer:
3 activities: {0,3}, {3,5}, {5,9} -> Option DQuick Check:
Greedy picks non-overlapping max activities [OK]
- Selecting overlapping activities
- Miscounting due to off-by-one errors
- Ignoring sorting step
Ready to prove it?
Pass the test and this pattern moves unknown
