Activity Selection Problem | Greedy Algo-1 - GeeksforGeeks

12 Jan, 2022
Greedy is an algorithmic paradigm that builds up a solution piece by piece, always choosing the next piece that offers the most obvious and immediate benefit. Greedy algorithms are used for optimization problems. An optimization problem can be solved using Greedy if the problem has the following property: At every step, we can make a choice that looks best at the moment, and we get the optimal solution of the complete problem. If a Greedy Algorithm can solve a problem, then it generally becomes the best method to solve that problem as the Greedy algorithms are in general more efficient than other techniques like Dynamic Programming. But Greedy algorithms cannot always be applied. For example, the Fractional Knapsack problem can be solved using Greedy, but 0-1 Knapsack cannot be solved using Greedy.Following are some standard algorithms that are Greedy algorithms. 1) Kruskal’s Minimum Spanning Tree (MST): In Kruskal’s algorithm, we create a MST by picking edges one by one. The Greedy Choice is to pick the smallest weight edge that doesn’t cause a cycle in the MST constructed so far. 2) Prim’s Minimum Spanning Tree: In Prim’s algorithm also, we create a MST by picking edges one by one. We maintain two sets: a set of the vertices already included in MST and the set of the vertices not yet included. The Greedy Choice is to pick the smallest weight edge that connects the two sets. 3) Dijkstra’s Shortest Path: Dijkstra’s algorithm is very similar to Prim’s algorithm. The shortest-path tree is built up, edge by edge. We maintain two sets: a set of the vertices already included in the tree and the set of the vertices not yet included. The Greedy Choice is to pick the edge that connects the two sets and is on the smallest weight path from source to the set that contains not yet included vertices. 4) Huffman Coding: Huffman Coding is a loss-less compression technique. It assigns variable-length bit codes to different characters. The Greedy Choice is to assign the least bit length code to the most frequent character.The greedy algorithms are sometimes also used to get an approximation for Hard optimization problems. For example, Traveling Salesman Problem is an NP-Hard problem. A Greedy choice for this problem is to pick the nearest unvisited city from the current city at every step. These solutions don’t always produce the best optimal solution but can be used to get an approximately optimal solution.Let us consider the Activity Selection problem as our first example of Greedy algorithms. Following is the problem statement. You are given n activities with their start and finish times. Select the maximum number of activities that can be performed by a single person, assuming that a person can only work on a single activity at a time.  
Example:  
Example 1 : Consider the following 3 activities sorted by
by finish time.
     start[]  =  {10, 12, 20};
     finish[] =  {20, 25, 30};
A person can perform at most two activities. The 
maximum set of activities that can be executed 
is {0, 2} [ These are indexes in start[] and 
finish[] ]

Example 2 : Consider the following 6 activities 
sorted by by finish time.
     start[]  =  {1, 3, 0, 5, 8, 5};
     finish[] =  {2, 4, 6, 7, 9, 9};
A person can perform at most four activities. The 
maximum set of activities that can be executed 
is {0, 1, 3, 4} [ These are indexes in start[] and 
finish[] ]
The greedy choice is to always pick the next activity whose finish time is least among the remaining activities and the start time is more than or equal to the finish time of the previously selected activity. We can sort the activities according to their finishing time so that we always consider the next activity as minimum finishing time activity.1) Sort the activities according to their finishing time 2) Select the first activity from the sorted array and print it. 3) Do the following for the remaining activities in the sorted array. .......a) If the start time of this activity is greater than or equal to the finish time of the previously selected activity then select this activity and print it.In the following C implementation, it is assumed that the activities are already sorted according to their finish time. 
C++
C
Java
C#
Python3
PHP
Javascript
// C++ program for activity selection problem.// The following implementation assumes that the activities// are already sorted according to their finish time#include <bits/stdc++.h>using namespace std; // Prints a maximum set of activities that can be done by a single// person, one at a time.//  n   -->  Total number of activities//  s[] -->  An array that contains start time of all activities//  f[] -->  An array that contains finish time of all activitiesvoid printMaxActivities(int s[], int f[], int n){    int i, j;     cout <<"Following activities are selected "<< endl;     // The first activity always gets selected    i = 0;    cout <<" "<< i;     // Consider rest of the activities    for (j = 1; j < n; j++)    {      // If this activity has start time greater than or      // equal to the finish time of previously selected      // activity, then select it      if (s[j] >= f[i])      {          cout <<" " << j;          i = j;      }    }} // driver program to test above functionint main(){    int s[] =  {1, 3, 0, 5, 8, 5};    int f[] =  {2, 4, 6, 7, 9, 9};    int n = sizeof(s)/sizeof(s[0]);    printMaxActivities(s, f, n);    return 0;}//this code contributed by shivanisinghss2110
// C program for activity selection problem.// The following implementation assumes that the activities// are already sorted according to their finish time#include<stdio.h> // Prints a maximum set of activities that can be done by a single// person, one at a time.//  n   -->  Total number of activities//  s[] -->  An array that contains start time of all activities//  f[] -->  An array that contains finish time of all activitiesvoid printMaxActivities(int s[], int f[], int n){    int i, j;     printf ("Following activities are selected n");     // The first activity always gets selected    i = 0;    printf("%d ", i);     // Consider rest of the activities    for (j = 1; j < n; j++)    {      // If this activity has start time greater than or      // equal to the finish time of previously selected      // activity, then select it      if (s[j] >= f[i])      {          printf ("%d ", j);          i = j;      }    }} // driver program to test above functionint main(){    int s[] =  {1, 3, 0, 5, 8, 5};    int f[] =  {2, 4, 6, 7, 9, 9};    int n = sizeof(s)/sizeof(s[0]);    printMaxActivities(s, f, n);    return 0;}
// The following implementation assumes that the activities// are already sorted according to their finish timeimport java.util.*;import java.lang.*;import java.io.*; class ActivitySelection{    // Prints a maximum set of activities that can be done by a single    // person, one at a time.    //  n   -->  Total number of activities    //  s[] -->  An array that contains start time of all activities    //  f[] -->  An array that contains finish time of all activities    public static void printMaxActivities(int s[], int f[], int n)    {    int i, j;          System.out.print("Following activities are selected : n");          // The first activity always gets selected    i = 0;    System.out.print(i+" ");          // Consider rest of the activities    for (j = 1; j < n; j++)    {         // If this activity has start time greater than or         // equal to the finish time of previously selected         // activity, then select it         if (s[j] >= f[i])         {              System.out.print(j+" ");              i = j;          }     }    }          // driver program to test above function    public static void main(String[] args)    {    int s[] =  {1, 3, 0, 5, 8, 5};    int f[] =  {2, 4, 6, 7, 9, 9};    int n = s.length;            printMaxActivities(s, f, n);    }     }
// The following implementation assumes// that the activities are already sorted// according to their finish timeusing System; class GFG{// Prints a maximum set of activities// that can be done by a single// person, one at a time.// n --> Total number of activities// s[] --> An array that contains start//         time of all activities// f[] --> An array that contains finish//         time of all activitiespublic static void printMaxActivities(int[] s,                                      int[] f, int n){int i, j; Console.Write("Following activities are selected : "); // The first activity always gets selectedi = 0;Console.Write(i + " "); // Consider rest of the activitiesfor (j = 1; j < n; j++){    // If this activity has start time greater than or    // equal to the finish time of previously selected    // activity, then select it    if (s[j] >= f[i])    {        Console.Write(j + " ");        i = j;    }}} // Driver Codepublic static void Main(){    int[] s = {1, 3, 0, 5, 8, 5};    int[] f = {2, 4, 6, 7, 9, 9};    int n = s.Length;             printMaxActivities(s, f, n);}} // This code is contributed// by ChitraNayal
"""The following implementation assumes that the activitiesare already sorted according to their finish time""" """Prints a maximum set of activities that can be done by asingle person, one at a time"""# n --> Total number of activities# s[]--> An array that contains start time of all activities# f[] --> An array that contains finish time of all activities def printMaxActivities(s , f ):    n = len(f)    print ("The following activities are selected")     # The first activity is always selected    i = 0    print (i,end=' ')     # Consider rest of the activities    for j in range(n):         # If this activity has start time greater than        # or equal to the finish time of previously        # selected activity, then select it        if s[j] >= f[i]:            print (j,end=' ')            i = j # Driver program to test above functions = [1 , 3 , 0 , 5 , 8 , 5]f = [2 , 4 , 6 , 7 , 9 , 9]printMaxActivities(s , f) # This code is contributed by Nikhil Kumar Singh
<?php// PHP program for activity selection problem.// The following implementation assumes that// the activities are already sorted according// to their finish time // Prints a maximum set of activities// that can be done by a single// person, one at a time.// n --> Total number of activities// s[] --> An array that contains start//         time of all activities// f[] --> An array that contains finish//         time of all activitiesfunction printMaxActivities($s, $f, $n){     echo "Following activities are selected " . "\n";     // The first activity always gets selected    $i = 0;    echo $i . " ";     // Consider rest of the activities    for ($j = 1; $j < $n; $j++)    {             // If this activity has start time greater    // than or equal to the finish time of    // previously selected activity, then select it    if ($s[$j] >= $f[$i])    {        echo $j . " ";        $i = $j;    }    }} // Driver Code$s = array(1, 3, 0, 5, 8, 5);$f = array(2, 4, 6, 7, 9, 9);$n = sizeof($s);printMaxActivities($s, $f, $n); // This code is contributed// by Akanksha Rai?>
<script>// The following implementation assumes that the activities// are already sorted according to their finish time     // Prints a maximum set of activities that can be done by a single    // person, one at a time.    //  n   -->  Total number of activities    //  s[] -->  An array that contains start time of all activities    //  f[] -->  An array that contains finish time of all activities    function printMaxActivities(s,f,n)    {        let i, j;        document.write("Following activities are selected : n");                 // The first activity always gets selected        i = 0;        document.write(i+" ");                 // Consider rest of the activities        for (j = 1; j < n; j++)        {                      // If this activity has start time greater than or             // equal to the finish time of previously selected             // activity, then select it             if (s[j] >= f[i])             {                  document.write(j+" ");                  i = j;              }        }    }         // Driver program to test above function    let s = [1, 3, 0, 5, 8, 5]    let f = [2, 4, 6, 7, 9, 9]    let n = s.length;    printMaxActivities(s, f, n);         // This code is contributed by avanitrachhadiya2155</script>
  
Following activities are selected n0 1 3 4 
 
How does Greedy Choice work for Activities sorted according to finish time? Let the given set of activities be S = {1, 2, 3, ...n} and activities are sorted by finish time. The greedy choice is to always pick activity 1. How come activity 1 always provides one of the optimal solutions. We can prove it by showing that if there is another solution B with the first activity other than 1, then there is also a solution A of the same size with activity 1 as the first activity. Let the first activity selected by B be k, then there always exist A = {B – {k}} U {1}.
 
(Note that the activities in B are independent and k has the smallest finishing time among all. Since k is not 1, finish(k) >= finish(1)).
 
How to implement when given activities are not sorted? We create a structure/class for activities. We sort all activities by finish time (Refer sort in C++ STL). Once we have activities sorted, we apply the same algorithm.Below image is an illustration of the above approach:   
 
 
Below is the implementation of the above approach:
 
C++
Java
Python3
Javascript
// C++ program for activity selection problem// when input activities may not be sorted.#include <bits/stdc++.h>using namespace std; // A job has a start time, finish time and profit.struct Activitiy{    int start, finish;}; // A utility function that is used for sorting// activities according to finish timebool activityCompare(Activitiy s1, Activitiy s2){    return (s1.finish < s2.finish);} // Returns count of the maximum set of activities that can// be done by a single person, one at a time.void printMaxActivities(Activitiy arr[], int n){    // Sort jobs according to finish time    sort(arr, arr+n, activityCompare);     cout << "Following activities are selected n";     // The first activity always gets selected    int i = 0;    cout << "(" << arr[i].start << ", " << arr[i].finish << "), ";     // Consider rest of the activities    for (int j = 1; j < n; j++)    {      // If this activity has start time greater than or      // equal to the finish time of previously selected      // activity, then select it      if (arr[j].start >= arr[i].finish)      {          cout << "(" << arr[j].start << ", "              << arr[j].finish << "), ";          i = j;      }    }} // Driver programint main(){    Activitiy arr[] = {{5, 9}, {1, 2}, {3, 4}, {0, 6},                                       {5, 7}, {8, 9}};    int n = sizeof(arr)/sizeof(arr[0]);    printMaxActivities(arr, n);    return 0;}
// Java program for activity selection problem// when input activities may not be sorted.import java.io.*;import java.util.*; // A job has a start time, finish time and profit.class Activity{  int start, finish;   // Constructor  public Activity(int start, int finish)  {    this.start = start;    this.finish = finish;  }} // class to define user defined comparatorclass Compare{   // A utility function that is used for sorting  // activities according to finish time  static void compare(Activity arr[], int n)  {    Arrays.sort(arr, new Comparator<Activity>()                {                  @Override                  public int compare(Activity s1, Activity s2)                  {                    return s1.finish - s2.finish;                  }                });  }} // Driver classclass GFG {   // Returns count of the maximum set of activities that  // can  // be done by a single person, one at a time.  static void printMaxActivities(Activity arr[], int n)  {    // Sort jobs according to finish time    Compare obj = new Compare();    obj.compare(arr, n);    System.out.println(      "Following activities are selected :");     // The first activity always gets selected    int i = 0;    System.out.print("(" + arr[i].start + ", "                     + arr[i].finish + "), ");     // Consider rest of the activities    for (int j = 1; j < n; j++)    {       // If this activity has start time greater than      // or equal to the finish time of previously      // selected activity, then select it      if (arr[j].start >= arr[i].finish)      {        System.out.print("(" + arr[j].start + ", "                         + arr[j].finish + "), ");        i = j;      }    }  }   // Driver code  public static void main(String[] args)  {     int n = 6;    Activity arr[] = new Activity[n];    arr[0] = new Activity(5, 9);    arr[1] = new Activity(1, 2);    arr[2] = new Activity(3, 4);    arr[3] = new Activity(0, 6);    arr[4] = new Activity(5, 7);    arr[5] = new Activity(8, 9);     printMaxActivities(arr, n);  }} // This code is contributed by Dharanendra L V.
''' Python program for activity selection problem when input activities may not be sorted.'''def MaxActivities(arr, n):    selected = []         # Sort jobs according to finish time    Activity.sort(key = lambda x : x[1])         # The first activity always gets selected    i = 0    selected.append(arr[i])     for j in range(1, n):             '''If this activity has start time greater than or         equal to the finish time of previously selected         activity, then select it'''      if arr[j][0] >= arr[i][1]:          selected.append(arr[j])          i = j    return selected # Driver codeActivity = [[5, 9], [1, 2], [3, 4], [0, 6],[5, 7], [8, 9]]n = len(Activity)selected = MaxActivities(Activity, n)print("Following activities are selected :")print(selected) # This cde is contributed by kshitijjainm
<script>/* JavaScript program for activity selection problem when input activities may not be sorted.*/function MaxActivities(arr, n){    let selected = [];         // Sort jobs according to finish time       Activity = Activity.sort(function(a,b) {    return a[1] - b[1];    });         // The first activity always gets selected    let i = 0    selected.push(arr[i]);     for(let j=1;j<n;j++){      /*If this activity has start time greater than or         equal to the finish time of previously selected         activity, then select it*/      if( arr[j][0] >= arr[i][1]){          selected.push(arr[j]);          i = j;      }    }    return selected;}// Driver codeActivity = [[5, 9], [1, 2], [3, 4], [0, 6],[5, 7], [8, 9]];n = Activity.length;selected = MaxActivities(Activity, n);document.write("Following activities are selected : <br>")console.log(selected)for(let i = 0;i<selected.length;i++)    document.write("("+selected[i]+"), ")</script>
  
Output: 
 
Following activities are selected 
(1, 2), (3, 4), (5, 7), (8, 9),
 
Time Complexity: It takes O(n log n) time if input activities may not be sorted. It takes O(n) time when it is given that input activities are always sorted.Using STL we can solve it as follows: 
 
CPP
Java
Javascript
// C++ program for activity selection problem// when input activities may not be sorted.#include <bits/stdc++.h>using namespace std; void SelectActivities(vector<int>s,vector<int>f){// Vector to store results.    vector<pair<int,int>>ans; // Minimum Priority Queue to sort activities in ascending order of finishing time (f[i]).     priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>p;     for(int i=0;i<s.size();i++){        // Pushing elements in priority queue where the key is f[i]        p.push(make_pair(f[i],s[i]));    }     auto it = p.top();    int start = it.second;    int end = it.first;    p.pop();    ans.push_back(make_pair(start,end));     while(!p.empty()){        auto itr = p.top();        p.pop();        if(itr.second >= end){            start = itr.second;            end = itr.first;            ans.push_back(make_pair(start,end));        }    }    cout << "Following Activities should be selected. " << endl << endl;     for(auto itr=ans.begin();itr!=ans.end();itr++){        cout << "Activity started at: " << (*itr).first << " and ends at  " << (*itr).second << endl;    }} // Driver programint main(){    vector<int>s = {1, 3, 0, 5, 8, 5};    vector<int>f = {2, 4, 6, 7, 9, 9};    SelectActivities(s,f);     return 0;}
// java program for the above approachimport java.io.*;import java.lang.*;import java.util.*; class GFG {   // Pair class  static class Pair {     int first;    int second;     Pair(int first, int second)    {      this.first = first;      this.second = second;    }  }   static void SelectActivities(int s[], int f[])  {     // Vector to store results.    ArrayList<Pair> ans = new ArrayList<>();     // Minimum Priority Queue to sort activities in    // ascending order of finishing time (f[i]).    PriorityQueue<Pair> p = new PriorityQueue<>(      (p1, p2) -> p1.first - p2.first);     for (int i = 0; i < s.length; i++) {      // Pushing elements in priority queue where the      // key is f[i]      p.add(new Pair(f[i], s[i]));    }     Pair it = p.poll();    int start = it.second;    int end = it.first;    ans.add(new Pair(start, end));     while (!p.isEmpty()) {      Pair itr = p.poll();      if (itr.second >= end) {        start = itr.second;        end = itr.first;        ans.add(new Pair(start, end));      }    }    System.out.println(      "Following Activities should be selected. \n");     for (Pair itr : ans) {      System.out.println(        "Activity started at: " + itr.first        + " and ends at  " + itr.second);    }  }   // Driver Code  public static void main(String[] args)  {     int s[] = { 1, 3, 0, 5, 8, 5 };    int f[] = { 2, 4, 6, 7, 9, 9 };     // Function call    SelectActivities(s, f);  }} // This code is contributed by Kingash.
<script>// javascript program for the above approach  // Pair classclass Pair{    constructor(first,second)    {        this.first = first;          this.second = second;    }} function SelectActivities(s,f){    // Vector to store results.    let ans = [];       // Minimum Priority Queue to sort activities in    // ascending order of finishing time (f[i]).    let p = [];       for (let i = 0; i < s.length; i++) {      // Pushing elements in priority queue where the      // key is f[i]      p.push(new Pair(f[i], s[i]));    }    p.sort(function(a,b){return a.first-b.first;});       let it = p.shift();    let start = it.second;    let end = it.first;    ans.push(new Pair(start, end));       while (p.length!=0) {      let itr = p.shift();      if (itr.second >= end) {        start = itr.second;        end = itr.first;        ans.push(new Pair(start, end));      }    }    document.write(      "Following Activities should be selected. <br>");       for(let itr of ans.values()) {      document.write(        "Activity started at: " + itr.first        + " and ends at  " + itr.second+"<br>");    }} // Driver Codelet s=[1, 3, 0, 5, 8, 5 ];let f=[2, 4, 6, 7, 9, 9 ];// Function callSelectActivities(s, f);  // This code is contributed by rag2127</script>
Following Activities should be selected. 

Activity started at: 1 and ends at  2
Activity started at: 3 and ends at  4
Activity started at: 5 and ends at  7
Activity started at: 8 and ends at  9
ukasp
Akanksha_Rai
zafir_ahmad
kshitijjainm
shivanisinghss2110
dharanendralv23
Kingash
avanitrachhadiya2155
rohitsingh07052
rag2127
surajv
tejaskanikdaley1996
amartyaghoshgfg
Activity Selection Problem
Amazon
Facebook
Flipkart
MakeMyTrip
Morgan Stanley
Visa
Greedy
Flipkart
Morgan Stanley
Amazon
MakeMyTrip
Visa
Facebook
Greedy
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Program for array rotation
Fractional Knapsack Problem
Program for Shortest Job First (or SJF) CPU Scheduling | Set 1 (Non- preemptive)
Difference between Prim's and Kruskal's algorithm for MST
Program for Least Recently Used (LRU) Page Replacement algorithm
Shortest Remaining Time First (Preemptive SJF) Scheduling Algorithm
Minimum Number of Platforms Required for a Railway/Bus Station
Graph Coloring | Set 2 (Greedy Algorithm)
Program for Page Replacement Algorithms | Set 2 (FIFO)
Greedy approach vs Dynamic programming