1. Brute Force — Exponential Subset Search
Intuition
Try every possible subset of activities using recursion. For each subset, check if all activities are mutually disjoint. Return the maximum size among valid subsets.
When to apply: When N is very small (N <= 15).
Algorithm
- Step 1: Define recursive helper solve(index, lastEnd).
- Step 2: Base case: if index == N, return 0.
- Step 3: Option 1: Skip activity index: call solve(index + 1, lastEnd).
- Step 4: Option 2: If start[index] >= lastEnd, take activity: 1 + solve(index + 1, end[index]).
- Step 5: Return max of take and skip.
#include <iostream>#include <vector>#include <algorithm> using namespace std; struct Activity { int start, end;}; class Solution {public: int solve(int idx, int lastEnd, const vector<Activity>& acts) { if (idx == acts.size()) return 0; int notTake = solve(idx + 1, lastEnd, acts); int take = 0; if (acts[idx].start >= lastEnd) { take = 1 + solve(idx + 1, acts[idx].end, acts); } return max(take, notTake); } int activitySelection(vector<int>& start, vector<int>& end) { int n = start.size(); vector<Activity> acts(n); for (int i = 0; i < n; ++i) { acts[i] = {start[i], end[i]}; } sort(acts.begin(), acts.end(), [](const Activity& a, const Activity& b) { return a.start < b.start; }); return solve(0, -1, acts); }}; int main() { Solution sol; vector<int> start = {1, 3, 0, 5, 8, 5}; vector<int> end = {2, 4, 6, 7, 9, 9}; cout << "Max Activities: " << sol.activitySelection(start, end) << endl; return 0;}Time & Space Complexity
- Time complexity:
O(2^N)— Branches twice at each of N activities, exploring 2N recursion states. - Space complexity:
O(N)— Depth of recursion tree is N.
Why Brute Force Doesn't Scale:
For N = 105, 2N exceeds the number of atoms in the universe. Greedy finish-time sorting achieves O(N log N) in ~15ms.
For N = 100,000: O(N log N) requires ~1.7 * 106 comparisons, completing well under 50ms.