Job Sequencing Problem - GeeksforGeeks

21 Apr, 2022
Given an array of jobs where every job has a deadline and associated profit if the job is finished before the deadline. It is also given that every job takes a single unit of time, so the minimum possible deadline for any job is 1. How to maximize total profit if only one job can be scheduled at a time.
Examples: 
Input: Four Jobs with following 
deadlines and profits
JobID  Deadline  Profit
  a      4        20   
  b      1        10
  c      1        40  
  d      1        30
Output: Following is maximum 
profit sequence of jobs
        c, a   


Input:  Five Jobs with following
deadlines and profits
JobID   Deadline  Profit
  a       2        100
  b       1        19
  c       2        27
  d       1        25
  e       3        15
Output: Following is maximum 
profit sequence of jobs
        c, a, e
A Simple Solution is to generate all subsets of a given set of jobs and check individual subsets for the feasibility of jobs in that subset. Keep track of maximum profit among all feasible subsets. The time complexity of this solution is exponential. This is a standard Greedy Algorithm problem. 
Following is the algorithm.
1) Sort all jobs in decreasing order of profit. 2) Iterate on jobs in decreasing order of profit.For each job , do the following : a)Find a time slot i, such that slot is empty and i < deadline and i is greatest.Put the job in this slot and mark this slot filled. b)If no such i exists, then ignore the job. 
The Following is the implementation of the above algorithm. 
C++
C
Java
Python3
C#
Javascript
// Program to find the maximum profit job sequence from a// given array of jobs with deadlines and profits#include <algorithm>#include <iostream>using namespace std; // A structure to represent a jobstruct Job {    char id; // Job Id    int dead; // Deadline of job    int profit; // Profit if job is over before or on                // deadline}; // This function is used for sorting all jobs according to// profitbool comparison(Job a, Job b){    return (a.profit > b.profit);} // Returns minimum number of platforms requiredvoid printJobScheduling(Job arr[], int n){    // Sort all jobs according to decreasing order of profit    sort(arr, arr + n, comparison);     int result[n]; // To store result (Sequence of jobs)    bool slot[n]; // To keep track of free time slots     // Initialize all slots to be free    for (int i = 0; i < n; i++)        slot[i] = false;     // Iterate through all given jobs    for (int i = 0; i < n; i++) {        // Find a free slot for this job (Note that we start        // from the last possible slot)        for (int j = min(n, arr[i].dead) - 1; j >= 0; j--) {            // Free slot found            if (slot[j] == false) {                result[j] = i; // Add this job to result                slot[j] = true; // Make this slot occupied                break;            }        }    }     // Print the result    for (int i = 0; i < n; i++)        if (slot[i])            cout << arr[result[i]].id << " ";} // Driver codeint main(){    Job arr[] = { { 'a', 2, 100 },                  { 'b', 1, 19 },                  { 'c', 2, 27 },                  { 'd', 1, 25 },                  { 'e', 3, 15 } };    int n = sizeof(arr) / sizeof(arr[0]);    cout << "Following is maximum profit sequence of jobs "            "\n";     // Function call    printJobScheduling(arr, n);    return 0;} // This code is contributed by Aditya Kumar (adityakumar129)
#include <stdbool.h>#include <stdio.h>#include <stdlib.h> // A structure to represent a jobtypedef struct Job {    char id; // Job Id    int dead; // Deadline of job    int profit; // Profit if job is over before or on deadline} Job; // This function is used for sorting all jobs according to// profitint compare(const void* a, const void* b){    Job* temp1 = (Job*)a;    Job* temp2 = (Job*)b;    return (temp2->profit - temp1->profit);} // Find minimum between two numbers.int min(int num1, int num2){    return (num1 > num2) ? num2 : num1;} // Returns minimum number of platforms requiredvoid printJobScheduling(Job arr[], int n){    // Sort all jobs according to decreasing order of profit    qsort(arr, n, sizeof(Job), compare);    //     sort(arr, arr+n, comparison);     int result[n]; // To store result (Sequence of jobs)    bool slot[n]; // To keep track of free time slots     // Initialize all slots to be free    for (int i = 0; i < n; i++)        slot[i] = false;     // Iterate through all given jobs    for (int i = 0; i < n; i++) {        // Find a free slot for this job (Note that we start        // from the last possible slot)        for (int j = min(n, arr[i].dead) - 1; j >= 0; j--) {            // Free slot found            if (slot[j] == false) {                result[j] = i; // Add this job to result                slot[j] = true; // Make this slot occupied                break;            }        }    }     // Print the result    for (int i = 0; i < n; i++)        if (slot[i])            printf("%c ", arr[result[i]].id);} // Driver codeint main(){    Job arr[] = { { 'a', 2, 100 },                  { 'b', 1, 19 },                  { 'c', 2, 27 },                  { 'd', 1, 25 },                  { 'e', 3, 15 } };    int n = sizeof(arr) / sizeof(arr[0]);    printf(        "Following is maximum profit sequence of jobs \n");     // Function call    printJobScheduling(arr, n);    return 0;} // This code is contributed by Aditya Kumar (adityakumar129)
// Program to find the maximum profit// job sequence from a given array// of jobs with deadlines and profitsimport java.util.*; class Job {    // Each job has a unique-id,profit and deadline    char id;    int deadline, profit;     // Constructors    public Job() {}     public Job(char id, int deadline, int profit)    {        this.id = id;        this.deadline = deadline;        this.profit = profit;    }     // Function to schedule the jobs take 2 arguments    // arraylist and no of jobs to schedule    void printJobScheduling(ArrayList<Job> arr, int t)    {        // Length of array        int n = arr.size();        // Sort all jobs according to decreasing order of        // profit        Collections.sort(arr,(a, b) -> b.profit - a.profit);         // To keep track of free time slots        boolean result[] = new boolean[t];         // To store result (Sequence of jobs)        char job[] = new char[t];         // Iterate through all given jobs        for (int i = 0; i < n; i++) {            // Find a free slot for this job (Note that we            // start from the last possible slot)            for (int j = Math.min(t - 1, arr.get(i).deadline - 1); j >= 0; j--) {                // Free slot found                if (result[j] == false) {                    result[j] = true;                    job[j] = arr.get(i).id;                    break;                }            }        }         // Print the sequence        for (char jb : job)            System.out.print(jb + " ");        System.out.println();    }     // Driver code    public static void main(String args[])    {        ArrayList<Job> arr = new ArrayList<Job>();        arr.add(new Job('a', 2, 100));        arr.add(new Job('b', 1, 19));        arr.add(new Job('c', 2, 27));        arr.add(new Job('d', 1, 25));        arr.add(new Job('e', 3, 15));         // Function call        System.out.println(            "Following is maximum profit sequence of jobs");         Job job = new Job();         // Calling function        job.printJobScheduling(arr, 3);    }} // This code is contributed by Aditya Kumar (adityakumar129)
# Program to find the maximum profit# job sequence from a given array# of jobs with deadlines and profits # function to schedule the jobs take 2# arguments array and no of jobs to schedule  def printJobScheduling(arr, t):     # length of array    n = len(arr)     # Sort all jobs according to    # decreasing order of profit    for i in range(n):        for j in range(n - 1 - i):            if arr[j][2] < arr[j + 1][2]:                arr[j], arr[j + 1] = arr[j + 1], arr[j]     # To keep track of free time slots    result = [False] * t     # To store result (Sequence of jobs)    job = ['-1'] * t     # Iterate through all given jobs    for i in range(len(arr)):         # Find a free slot for this job        # (Note that we start from the        # last possible slot)        for j in range(min(t - 1, arr[i][1] - 1), -1, -1):             # Free slot found            if result[j] is False:                result[j] = True                job[j] = arr[i][0]                break     # print the sequence    print(job)  # Driver COdearr = [['a', 2, 100],  # Job Array       ['b', 1, 19],       ['c', 2, 27],       ['d', 1, 25],       ['e', 3, 15]]  print("Following is maximum profit sequence of jobs") # Function CallprintJobScheduling(arr, 3) # This code is contributed# by Anubhav Raj Singh
// C# Program to find the maximum profit// job sequence from a given array// of jobs with deadlines and profits using System;using System.Collections.Generic; class GFG : IComparer<Job>{    public int Compare(Job x, Job y)    {        if (x.profit == 0 || y.profit== 0)        {            return 0;        }                   // CompareTo() method        return (y.profit).CompareTo(x.profit);               }}  public class Job{         // Each job has a unique-id,    // profit and deadline    char id;    public int deadline, profit;      // Constructors    public Job() {}      public Job(char id, int deadline, int profit)    {        this.id = id;        this.deadline = deadline;        this.profit = profit;    }      // Function to schedule the jobs take 2    // arguments arraylist and no of jobs to schedule    void printJobScheduling(List<Job> arr, int t)    {        // Length of array        int n = arr.Count;          GFG gg = new GFG();        // Sort all jobs according to        // decreasing order of profit        arr.Sort(gg);          // To keep track of free time slots        bool[] result = new bool[t];          // To store result (Sequence of jobs)        char[] job = new char[t];          // Iterate through all given jobs        for (int i = 0; i < n; i++)        {            // Find a free slot for this job            // (Note that we start from the            // last possible slot)            for (int j                 = Math.Min(t - 1, arr[i].deadline - 1);                 j >= 0; j--) {                  // Free slot found                if (result[j] == false)                {                    result[j] = true;                    job[j] = arr[i].id;                    break;                }            }        }          // Print the sequence        foreach (char jb in job)        {            Console.Write(jb + " ");        }        Console.WriteLine();    }      // Driver code    static public void Main ()    {                 List<Job> arr = new List<Job>();          arr.Add(new Job('a', 2, 100));        arr.Add(new Job('b', 1, 19));        arr.Add(new Job('c', 2, 27));        arr.Add(new Job('d', 1, 25));        arr.Add(new Job('e', 3, 15));                // Function call        Console.WriteLine("Following is maximum "                           + "profit sequence of jobs");          Job job = new Job();          // Calling function        job.printJobScheduling(arr, 3);             }} // This code is contributed by avanitracchadiya2155.
<script> // Program to find the maximum profit// job sequence from a given array// of jobs with deadlines and profits // function to schedule the jobs take 2// arguments array and no of jobs to schedule function printJobScheduling(arr, t){    // length of array    let n = arr.length;     // Sort all jobs according to    // decreasing order of profit    for(let i=0;i<n;i++){        for(let j = 0;j<(n - 1 - i);j++){            if(arr[j][2] < arr[j + 1][2]){                let temp = arr[j];                arr[j] = arr[j + 1];                arr[j + 1] = temp;            }         }     }     // To keep track of free time slots    let result = [];     // To store result (Sequence of jobs)    let job = [];    for(let i = 0;i<t;i++){        job[i] = '-1';        result[i] = false;    }     // Iterate through all given jobs    for(let i= 0;i<arr.length;i++){        // Find a free slot for this job        // (Note that we start from the        // last possible slot)        for(let j = (t - 1, arr[i][1] - 1);j>=0;j--){            // Free slot found            if(result[j] == false){                result[j] = true;                job[j] = arr[i][0];                break;            }        }    }     // print the sequence    document.write(job);} // Driver COdearr = [['a', 2, 100],  // Job Array       ['b', 1, 19],       ['c', 2, 27],       ['d', 1, 25],       ['e', 3, 15]]; document.write("Following is maximum profit sequence of jobs ");document.write("<br>"); // Function CallprintJobScheduling(arr, 3) ; </script>
  
Following is maximum profit sequence of jobs 
c a e 
 
The Time Complexity of the above solution is O(n2). It can be optimized using Priority Queue(max heap).
 
The algorithm goes as follow:
 
Sort the jobs based on their deadlines.
Iterate from the end and calculate the available slots between every two consecutive deadlines. Include the profit, deadline, and job ID of ith job in the max heap.
While the slots are available and there are jobs left in the max heap, include the job ID with maximum profit and deadline in the result.
Sort the result array based on their deadlines.
 
Here is the implementation of the above algorithm.
 
C++
Java
Python3
#include <bits/stdc++.h> using namespace std; // A structure to represent a jobstruct Job {    char id; // Job Id    int dead; // Deadline of job    int profit; // Profit earned if job is completed before                // deadline}; // Custom sorting helper struct which is used for sorting// all jobs according to profitstruct jobProfit {    bool operator()(Job const& a, Job const& b)    {        return (a.profit < b.profit);    }}; // Returns minimum number of platforms requiredvoid printJobScheduling(Job arr[], int n){    vector<Job> result;    sort(arr, arr + n,         [](Job a, Job b) { return a.dead < b.dead; });    // set a custom priority queue    priority_queue<Job, vector<Job>, jobProfit> pq;    for (int i = n - 1; i >= 0; i--) {        int slot_available;        // we count the slots available between two jobs        if (i == 0) {            slot_available = arr[i].dead;        }        else {            slot_available = arr[i].dead - arr[i - 1].dead;        }        // include the profit of job(as priority),        // deadline and job_id in maxHeap        pq.push(arr[i]);        while (slot_available > 0 && pq.size() > 0) {            // get the job with the most profit            Job job = pq.top();            pq.pop();            // reduce the slots            slot_available--;            // add it to the answer            result.push_back(job);        }    }    // sort the result based on the deadline    sort(result.begin(), result.end(),         [&](Job a, Job b) { return a.dead < b.dead; });    // print the result    for (int i = 0; i < result.size(); i++)        cout << result[i].id << ' ';    cout << endl;} int main(){    // Driver code    Job arr[] = { { 'a', 2, 100 },                  { 'b', 1, 19 },                  { 'c', 2, 27 },                  { 'd', 1, 25 },                  { 'e', 3, 15 } };    int n = sizeof(arr) / sizeof(arr[0]);    cout << "Following is maximum profit sequence of jobs "            "\n";     // Function call    printJobScheduling(arr, n);    return 0;} // This code is contributed By Reetu Raj Dubey
// Java implementation of above approach // Program to find the maximum profit// job sequence from a given array// of jobs with deadlines and profitsimport java.util.*; class GFG {     // a class to represent job    static class Job {        char job_id;        int deadline;        int profit;        Job(char job_id, int deadline, int profit)        {            this.deadline = deadline;            this.job_id = job_id;            this.profit = profit;        }    }     static void printJobScheduling(ArrayList<Job> arr)    {        int n = arr.size();         // sorting the array on the        // basis of their deadlines        Collections.sort(arr, (a, b) -> {            return a.deadline - b.deadline;        });         // initialise the result array and maxHeap        ArrayList<Job> result = new ArrayList<>();        PriorityQueue<Job> maxHeap = new PriorityQueue<>(            (a, b) -> { return b.profit - a.profit; });         // starting the iteration from the end        for (int i = n - 1; i > -1; i--) {            int slot_available;            // calculate slots between two deadlines            if (i == 0) {                slot_available = arr.get(i).deadline;            }            else {                slot_available = arr.get(i).deadline                                 - arr.get(i - 1).deadline;            }             // include the profit of job(as priority),            // deadline and job_id in maxHeap            maxHeap.add(arr.get(i));             while (slot_available > 0                   && maxHeap.size() > 0) {                 // get the job with max_profit                Job job = maxHeap.remove();                 // reduce the slots                slot_available--;                 // include the job in the result array                result.add(job);            }        }         // jobs included might be shuffled        // sort the result array by their deadlines        Collections.sort(result, (a, b) -> {            return a.deadline - b.deadline;        });        for (Job job : result) {            System.out.print(job.job_id + " ");        }        System.out.println();    }     // Driver Code    public static void main(String[] args)    {        ArrayList<Job> arr = new ArrayList<Job>();         arr.add(new Job('a', 2, 100));        arr.add(new Job('b', 1, 19));        arr.add(new Job('c', 2, 27));        arr.add(new Job('d', 1, 25));        arr.add(new Job('e', 3, 15));        // Function call        System.out.println("Following is maximum "                           + "profit sequence of jobs");         // Calling function        printJobScheduling(arr);    }} // This code is contributed by Karandeep Singh
# Program to find the maximum profit# job sequence from a given array# of jobs with deadlines and profitsimport heapq  def printJobScheduling(arr):    n = len(arr)     # arr[i][0] = job_id, arr[i][1] = deadline, arr[i][2] = profit     # sorting the array on the    # basis of their deadlines    arr.sort(key=lambda x: x[1])     # initialise the result array and maxHeap    result = []    maxHeap = []     # starting the iteration from the end    for i in range(n - 1, -1, -1):         # calculate slots between two deadlines        if i == 0:            slots_available = arr[i][1]        else:            slots_available = arr[i][1] - arr[i - 1][1]         # include the profit of job(as priority), deadline        # and job_id in maxHeap        # note we push negative value in maxHeap to convert        # min heap to max heap in python        heapq.heappush(maxHeap, (-arr[i][2], arr[i][1], arr[i][0]))         while slots_available and maxHeap:             # get the job with max_profit            profit, deadline, job_id = heapq.heappop(maxHeap)             # reduce the slots            slots_available -= 1             # include the job in the result array            result.append([job_id, deadline])     # jobs included might be shuffled    # sort the result array by their deadlines    result.sort(key=lambda x: x[1])     for job in result:        print(job[0], end=" ")    print()  # Driver COdearr = [['a', 2, 100],  # Job Array       ['b', 1, 19],       ['c', 2, 27],       ['d', 1, 25],       ['e', 3, 15]] print("Following is maximum profit sequence of jobs") # Function CallprintJobScheduling(arr) # This code is contributed# by Shivam Bhagat
Following is maximum profit sequence of jobs
a c e 
Time complexity : O(nlog(n))
Space complexity : O(n)
It can also be optimized using Disjoint Set Data Structure. Please refer to the below post for details. 
YouTubeGeeksforGeeks507K subscribersJob Sequencing Problem (Greedy Algorithm) | GeeksforGeeksWatch laterShareCopy linkInfoShoppingTap to unmuteIf playback doesn't begin shortly, try restarting your device.You're signed outVideos you watch may be added to the TV's watch history and influence TV recommendations. To avoid this, cancel and sign in to YouTube on your computer.CancelConfirmMore videosMore videosSwitch cameraShareInclude playlistAn error occurred while retrieving sharing information. Please try again later.Watch on0:000:000:00 / 6:24•Live•<div class="player-unavailable"><h1 class="message">An error occurred.</h1><div class="submessage"><a href="https://www.youtube.com/watch?v=R6Skj4bT1HE" target="_blank">Try watching this video on www.youtube.com</a>, or enable JavaScript if it is disabled in your browser.</div></div>
Job Sequencing Problem | Set 2 (Using Disjoint Set) 
Sources: http://ocw.mit.edu/courses/civil-and-environmental-engineering/1-204-computer-algorithms-in-systems-engineering-spring-2010/lecture-notes/MIT1_204S10_lec10.pdfThis article is contributed by Shubham. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
anubhavraj_08
coder72
PrateekGupta10
siddharthchauhan
rohitsingh07052
umeshg17
avanitrachhadiya2155
surinderdawra388
sumitgumber28
shivampkrr
karandeep1234
mreeturaj1234
adityakumar129
Accolite
Greedy
Accolite
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