Activity Selection

Last Updated : 22 Sep, 2026

Given two arrays start[] and finish[], representing the start and finish times of activities. A person can perform only one activity at a time, and an activity can be performed only if its start time is greater than the finish time of the last chosen activity.
Find the maximum number of activities that can be performed without overlapping.

Examples:  

Input: start[] = [1, 3, 0, 5, 8, 5], finish[] = [2, 4, 6, 7, 9, 9]
Output: 4
Explanation: A person can perform at most four activities. The maximum set of activities that can be performed is {0, 1, 3, 4} (these are the indexes in the start[] and finish[] arrays).

Input: start[] = [10, 12, 20], finish[] = [20, 25, 30]
Output: 1
Explanation: A person can perform at most one activity.

Try It Yourself
redirect icon

[Naive Approach] Generate All Subsets - O(2n) Time and O(n) Space

Generates all possible subsets of activities, where each subset represents a potential selection.

For each subset, we check if the activities are mutually non-overlapping by comparing their time intervals pairwise.

If a subset is valid and contains more activities than our current maximum, we update the maximum count.

Note: Generating all possible subsets and checks them one by one will lead to an exponential time complexity, which becomes impossible to compute for larger values of n. Hence, this approach is not practical.

[Expected Approach 1] Sorting - O(n * log(n)) Time and O(n) Space

The problem can be solved using a greedy approach. The idea is that whenever multiple activities overlap, we should pick the one that finishes earliest, because finishing sooner leaves the most room to schedule upcoming activities.

To achieve this, we sort all activities by their finishing times. Then, starting with the first one, we repeatedly pick the next activity that both starts after the last selected activity ends and has the earliest finish time among the remaining ones.


C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int activitySelection(vector<int> &start, vector<int> &finish) {
    int n = start.size();
    vector<vector<int>> arr(n, vector<int>(2));

    for (int i = 0; i < n; i++) {
        arr[i][0] = start[i];
        arr[i][1] = finish[i];
    }

    // Sort activities by finish time
    sort(arr.begin(), arr.end(),
         [](const vector<int>& a, const vector<int>& b) {
             return a[1] < b[1];
         });

    int count = 1;
    int j = 0;

    for (int i = 1; i < n; i++) {

        // Select the activity if it starts after the last one finishes
        if (arr[i][0] > arr[j][1]) {
            count++;
            j = i;
        }
    }

    return count;
}

int main() {
    vector<int> start = {1, 3, 0, 5, 8, 5};
    vector<int> finish = {2, 4, 6, 7, 9, 9};

    cout << activitySelection(start, finish) << endl;

    return 0;
}
Java
import java.util.Arrays;
import java.util.Comparator;

public class GfG {
    
    public static int activitySelection(int[] start, int[] finish) {
        int n = start.length;
        int[][] arr = new int[n][2];
        for (int i = 0; i < n; i++) {
            arr[i][0] = start[i];
            arr[i][1] = finish[i];
        }

        // Sort activities by finish time
        Arrays.sort(arr, Comparator.comparingInt(a -> a[1]));
        
        // At least one activity can be performed
        int count = 1;
        
        // Index of last selected activity
        int j = 0;

        for (int i = 1; i < n; i++) {
            
            // Check if current activity starts
            // after last selected activity finishes
            if (arr[i][0] > arr[j][1]) {
                count++;
                
                // Update last selected activity
                j = i;
            }
        }

        return count;
    }

    public static void main(String[] args) {
        int[] start = {1, 3, 0, 5, 8, 5};
        int[] finish = {2, 4, 6, 7, 9, 9};
        System.out.println(activitySelection(start, finish));
    }
}
Python
def activitySelection(start, finish):
    arr = list(zip(start, finish))

    # Sort activities by finish time
    arr.sort(key=lambda x: x[1])
    
    # At least one activity can be performed
    count = 1
    
    # Index of last selected activity
    j = 0

    for i in range(1, len(arr)):
        
        # Check if current activity starts
        # after last selected activity finishes
        if arr[i][0] > arr[j][1]:
            count += 1
            
            # Update last selected activity
            j = i

    return count

if __name__ == '__main__':
    start = [1, 3, 0, 5, 8, 5]
    finish = [2, 4, 6, 7, 9, 9]
    print(activitySelection(start, finish))
C#
using System;
using System.Collections.Generic;

public class GfG {
    public static int activitySelection(int[] start, int[] finish) {
        List<List<int>> arr = new List<List<int>>();
        for (int i = 0; i < start.Length; i++) {
            arr.Add(new List<int> { start[i], finish[i] });
        }

        // Sort activities by finish time
        arr.Sort((a, b) => a[1].CompareTo(b[1]));
        
        // At least one activity can be performed
        int count = 1;  

        // Index of last selected activity
        int j = 0;      

        for (int i = 1; i < arr.Count; i++) {

            // Check if current activity starts
            // after last selected activity finishes
            if (arr[i][0] > arr[j][1]) {
                count++;

                // Update last selected activity
                j = i;  
            }
        }

        return count;
    }

    public static void Main() {
        int[] start = new int[] { 1, 3, 0, 5, 8, 5 };
        int[] finish = new int[] { 2, 4, 6, 7, 9, 9 };
        Console.WriteLine(activitySelection(start, finish));
    }
}
JavaScript
function activitySelection(start, finish) {
    let arr = [];
    for (let i = 0; i < start.length; i++) {
        arr.push([start[i], finish[i]]);
    }

    // Sort activities by finish time
    arr.sort((a, b) => a[1] - b[1]);
    
    // At least one activity can be performed
    let count = 1;  
    
    // Index of last selected activity
    let j = 0;      

    for (let i = 1; i < arr.length; i++) {
        
        // Check if current activity starts
        // after last selected activity finishes
        if (arr[i][0] > arr[j][1]) {
            count++;
            
            // Update last selected activity
            j = i;  
        }
    }

    return count;
}
// Driver Code
const start = [1, 3, 0, 5, 8, 5];
const finish = [2, 4, 6, 7, 9, 9];
console.log(activitySelection(start, finish));

Output
4

[Expected Approach 2] Priority Queue - O(n * log(n)) Time and O(n) Space

Instead of sorting, we can also use a min-heap (priority queue) to directly process activities in order of their finishing time.

By storing each activity as (finish, start) in the heap, the activity with the earliest finish time is always available at the top.

We then apply the same greedy rule as above: pick it if its start time is after the last chosen activity's finish, update the finish time, and continue.

C++
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int activitySelection(vector<int> &start, vector<int> &finish) {
   
    int ans = 0;

    // Minimum Priority Queue to sort activities in
    // ascending order of finishing time (end[i]).
    priority_queue<pair<int, int>, 
        vector<pair<int, int>>, greater<pair<int, int>>> p;

    for (int i = 0; i < start.size(); i++) {
        p.push(make_pair(finish[i], start[i]));
    }

    // to store the end time of last activity
    int finishtime = -1;

    while (!p.empty()) {
        
        pair<int, int> activity = p.top();
        p.pop();
        
        if (activity.second > finishtime)
        {
            finishtime = activity.first;
            ans++;
        }
    }
    
    return ans;
}

int main() {
    
    vector<int> start = {1, 3, 0, 5, 8, 5};
    vector<int> finish = {2, 4, 6, 7, 9, 9};
    cout << activitySelection(start, finish);
    return 0;
}
Java
import java.util.PriorityQueue;

class GFG {

    static int activitySelection(int[] start, int[] finish) {
        int n = start.length;
        int ans = 0;

        // Min Heap to store activities in ascending order
        // of finish time
        PriorityQueue<int[]> p = new PriorityQueue<>(
            (a, b) -> Integer.compare(a[0], b[0]));

        for (int i = 0; i < n; i++) {
            p.add(new int[] { finish[i], start[i] });
        }

        // to store the end time of the last selected activity
        int finishtime = -1;

        while (!p.isEmpty()) {
            int[] activity
                = p.poll(); 
            if (activity[1] > finishtime) {
                finishtime = activity[0];
                ans++;
            }
        }

        return ans;
    }

    public static void main(String[] args) {
        int[] start = { 1, 3, 0, 5, 8, 5 };
        int[] finish = { 2, 4, 6, 7, 9, 9 };

        System.out.println(
            activitySelection(start, finish));
    }
}
Python
import heapq

def activitySelection(start, finish):

    ans = 0

    # Minimum Priority Queue to sort activities in
    # ascending order of finishing time (end[i]).
    p = []
    for i in range(len(start)):
        heapq.heappush(p, (finish[i], start[i]))

    # to store the end time of last activity
    finishtime = -1

    while p:
        activity = heapq.heappop(p)
        if activity[1] > finishtime:
            finishtime = activity[0]
            ans += 1

    return ans


if __name__ == "__main__":
    start = [1, 3, 0, 5, 8, 5]
    finish = [2, 4, 6, 7, 9, 9]
    print(activitySelection(start, finish))
C#
using System;
using System.Collections.Generic;

class GFG {

    static int activitySelection(int[] start, int[] finish) {
        int n = start.Length;
        int ans = 0;

        // Min Heap to store activities in ascending order
        // of finish time
        PriorityQueue<int[], int> p = new PriorityQueue<int[], int>();

        for (int i = 0; i < n; i++) {
            p.Enqueue(
                new int[] { finish[i], start[i] },
                finish[i]
            );
        }

        // To store the end time of the last selected activity
        int finishtime = -1;

        while (p.Count > 0) {
            int[] activity = p.Dequeue();

            if (activity[1] > finishtime) {
                finishtime = activity[0];
                ans++;
            }
        }

        return ans;
    }

    public static void Main(string[] args) {
        int[] start = { 1, 3, 0, 5, 8, 5 };
        int[] finish = { 2, 4, 6, 7, 9, 9 };

        Console.WriteLine(
            activitySelection(start, finish));
    }
}
JavaScript
class PriorityQueue {
    constructor() {
        this.heap = [];
    }

    enqueue(element, priority) {
        this.heap.push({ element, priority });

        let i = this.heap.length - 1;

        while (i > 0) {
            let parent = Math.floor((i - 1) / 2);

            if (this.heap[parent].priority <= this.heap[i].priority)
                break;

            [this.heap[parent], this.heap[i]] =
                [this.heap[i], this.heap[parent]];

            i = parent;
        }
    }

    dequeue() {
        let root = this.heap[0];
        let last = this.heap.pop();

        if (this.heap.length > 0) {
            this.heap[0] = last;
            let i = 0;

            while (true) {
                let left = 2 * i + 1;
                let right = 2 * i + 2;
                let smallest = i;

                if (left < this.heap.length &&
                    this.heap[left].priority < this.heap[smallest].priority)
                    smallest = left;

                if (right < this.heap.length &&
                    this.heap[right].priority < this.heap[smallest].priority)
                    smallest = right;

                if (smallest === i)
                    break;

                [this.heap[i], this.heap[smallest]] =
                    [this.heap[smallest], this.heap[i]];

                i = smallest;
            }
        }

        return root.element;
    }

    isEmpty() {
        return this.heap.length === 0;
    }
}

function activitySelection(start, finish) {
    let n = start.length;
    let ans = 0;

    // Min Heap to store activities in ascending order
    // of finish time
    let p = new PriorityQueue();

    for (let i = 0; i < n; i++) {
        p.enqueue(
            { finish: finish[i], start: start[i] },
            finish[i]
        );
    }

    // To store the end time of the last selected activity
    let finishtime = -1;

    while (!p.isEmpty()) {
        let activity = p.dequeue();

        if (activity.start > finishtime) {
            finishtime = activity.finish;
            ans++;
        }
    }

    return ans;
}

// Driver Code
let start = [1, 3, 0, 5, 8, 5];
let finish = [2, 4, 6, 7, 9, 9];

console.log(activitySelection(start, finish));

Output
4
Comment