Weighted Job Scheduling Memoization Solution in O(n Log n) time

Last Updated : 6 Oct, 2025

Given n jobs where every job has the following properties:

  • Start Time
  • Finish Time
  • Profit or Value Associated

The task is to find the maximum profit in scheduling jobs such that no two jobs overlap.

Examples: 

Input: jobs[][] = [[1, 2, 50],
[3, 5, 20],
[6, 19, 100],
[2, 100, 200]]
Output: 250
Explanation:

  • Job (1, 2, 50) can be chosen first.
  • Job (3, 5, 20) can be skipped because it's not the most profitable choice compared to Job (6, 19, 100).
  • Job (6, 19, 100) can be selected next.
  • Job (2, 100, 200) is skipped as it overlaps with Job (1, 2, 50).

Thus, the selected jobs are Job 1 and Job 3, resulting in a total profit of 50 + 200 = 250.

Input: jobs[][] = [[1, 3, 60],
[2, 5, 50],
[4, 6, 70],
[5, 7, 30]]
Output: 130
Explanation:

  • Job (1, 3, 60) is selected.
  • Job (2, 5, 50) is skipped as it overlaps with Job (1, 3, 60).
  • Job (4, 6, 70) is selected.
  • Job (5, 7, 30) is skipped as it overlaps with Job (4, 6, 70).

The total maximum profit here is 60 (Job 1) + 70 (Job 3) = 130.

Approach:

We have discussed recursive and Dynamic Programming-based approaches in the Weighted Job Scheduling.

The problem of finding the maximum profit in scheduling non-overlapping jobs can be solved using dynamic programming. The approach begins by sorting the jobs in ascending order based on their start times, which helps efficiently identify the next non-overlapping job using binary search. The recursive solution explores two options for each job: either include it in the schedule, adding its profit and recursively calculating the profit of the next compatible job, or exclude it and move on to the next job. Memoization is used to store previously calculated results for subproblems to avoid redundant calculations. The function returns the maximum profit by selecting the optimal combination of jobs, ensuring that no two jobs overlap.

C++
// C++ program to implement
// Weighted Job Scheduling
#include <bits/stdc++.h>
using namespace std;

// Function to find the closest next job.
int findNextJob(int i, vector<vector<int>> &jobs) {
    int end = jobs[i][1];
    int ans = jobs.size();
    int s = i + 1, e = jobs.size() - 1;
    while (s <= e) {
        int mid = s + (e - s) / 2;
        if (jobs[mid][0] >= end) {
            ans = mid;
            e = mid - 1;
        }
        else {
            s = mid + 1;
        }
    }
    return ans;
}

int maxProfitRecur(int i, vector<vector<int>> &jobs, vector<int> &memo) {
    if (i == jobs.size())
        return 0;

    // If value is memoized
    if (memo[i] != -1)
        return memo[i];

    // Find the next closest job if
    // current job is chosen.
    int next = findNextJob(i, jobs);

    // Find maximum profit if current job
    // is chosen.
    int take = jobs[i][2] + maxProfitRecur(next, jobs, memo);

    // Find maximum profit if current
    // job is skipped.
    int noTake = maxProfitRecur(i + 1, jobs, memo);

    return memo[i] = max(take, noTake);
}

int maxProfit(vector<vector<int>> &jobs) {
    int n = jobs.size();

    // Sort the jobs in increasing order
    // of start time and end time.
    sort(jobs.begin(), jobs.end());

    // Array for memoization.
    vector<int> memo(n, -1);
    return maxProfitRecur(0, jobs, memo);
}

int main() {
    vector<vector<int>> jobs = 
    {{1, 2, 50}, {3, 5, 20}, {6, 19, 100}, {2, 100, 200}};
    cout << maxProfit(jobs);
    return 0;
}
Java
// Java program to implement
// Weighted Job Scheduling

import java.util.*;

class GfG {
    static int findNextJob(int i, int[][] jobs) {
        int end = jobs[i][1];
        int ans = jobs.length;
        int s = i + 1, e = jobs.length - 1;
        while (s <= e) {
            int mid = s + (e - s) / 2;
            if (jobs[mid][0] >= end) {
                ans = mid;
                e = mid - 1;
            }
            else {
                s = mid + 1;
            }
        }
        return ans;
    }

    static int maxProfitRecur(int i, int[][] jobs,
                              int[] memo) {
        if (i == jobs.length)
            return 0;

        // If value is memoized
        if (memo[i] != -1)
            return memo[i];

        // Find the next closest job if
        // current job is chosen.
        int next = findNextJob(i, jobs);

        // Find maximum profit if current job
        // is chosen.
        int take
            = jobs[i][2] + maxProfitRecur(next, jobs, memo);

        // Find maximum profit if current
        // job is skipped.
        int noTake = maxProfitRecur(i + 1, jobs, memo);

        return memo[i] = Math.max(take, noTake);
    }

    static int maxProfit(int[][] jobs) {
        int n = jobs.length;

        // Sort the jobs in increasing order
        // of start time and end time.
        Arrays.sort(jobs, (a, b) -> {
            if (a[0] == b[0])
                return Integer.compare(a[1], b[1]);
            return Integer.compare(a[0], b[0]);
        });

        // Array for memoization.
        int[] memo = new int[n];
        Arrays.fill(memo, -1);
        return maxProfitRecur(0, jobs, memo);
    }

    public static void main(String[] args) {
        int[][] jobs = { { 1, 2, 50 },
                         { 3, 5, 20 },
                         { 6, 19, 100 },
                         { 2, 100, 200 } };
        System.out.println(maxProfit(jobs));
    }
}
Python
# Python program to implement
# Weighted Job Scheduling

def findNextJob(i, jobs):
    end = jobs[i][1]
    ans = len(jobs)
    s, e = i + 1, len(jobs) - 1
    while s <= e:
        mid = s + (e - s) // 2
        if jobs[mid][0] >= end:
            ans = mid
            e = mid - 1
        else:
            s = mid + 1
    return ans


def maxProfitRecur(i, jobs, memo):
    if i == len(jobs):
        return 0

    # If value is memoized
    if memo[i] != -1:
        return memo[i]

    # Find the next closest job if
    # current job is chosen.
    next = findNextJob(i, jobs)

    # Find maximum profit if current job
    # is chosen.
    take = jobs[i][2] + maxProfitRecur(next, jobs, memo)

    # Find maximum profit if current
    # job is skipped.
    noTake = maxProfitRecur(i + 1, jobs, memo)

    memo[i] = max(take, noTake)
    return memo[i]


def maxProfit(jobs):
    jobs.sort()
    memo = [-1] * len(jobs)
    return maxProfitRecur(0, jobs, memo)


if __name__ == "__main__":
    jobs = [
        [1, 2, 50], [3, 5, 20],
        [6, 19, 100], [2, 100, 200]
    ]
    print(maxProfit(jobs))
C#
// C# program to implement
// Weighted Job Scheduling

using System;
using System.Linq;

class GfG {

    static int findNextJob(int i, int[][] jobs) {
        int end = jobs[i][1];
        int ans = jobs.Length;
        int s = i + 1, e = jobs.Length - 1;
        while (s <= e) {
            int mid = s + (e - s) / 2;
            if (jobs[mid][0] >= end) {
                ans = mid;
                e = mid - 1;
            }
            else {
                s = mid + 1;
            }
        }
        return ans;
    }

    static int maxProfitRecur(int i, int[][] jobs,
                              int[] memo) {
        if (i == jobs.Length)
            return 0;

        // If value is memoized
        if (memo[i] != -1)
            return memo[i];

        // Find the next closest job if
        // current job is chosen.
        int next = findNextJob(i, jobs);

        // Find maximum profit if current job
        // is chosen.
        int take
            = jobs[i][2] + maxProfitRecur(next, jobs, memo);

        // Find maximum profit if current
        // job is skipped.
        int noTake = maxProfitRecur(i + 1, jobs, memo);

        memo[i] = Math.Max(take, noTake);
        return memo[i];
    }

    static int maxProfit(int[][] jobs) {
        Array.Sort(jobs,(a, b) => a[0] == b[0] ? a[1].CompareTo(b[1]) : a[0].CompareTo(b[0]));

        int[] memo = new int[jobs.Length];
        Array.Fill(memo, -1);
        return maxProfitRecur(0, jobs, memo);
    }

    static void Main(string[] args) {
        int[][] jobs = { new int[] { 1, 2, 50 },
                         new int[] { 3, 5, 20 },
                         new int[] { 6, 19, 100 },
                         new int[] { 2, 100, 200 } };
        Console.WriteLine(maxProfit(jobs));
    }
}
JavaScript
// JavaScript program to implement
// Weighted Job Scheduling

function findNextJob(i, jobs) {
    const end = jobs[i][1];
    let ans = jobs.length;
    let s = i + 1, e = jobs.length - 1;
    while (s <= e) {
        const mid = s + Math.floor((e - s) / 2);
        if (jobs[mid][0] >= end) {
            ans = mid;
            e = mid - 1;
        }
        else {
            s = mid + 1;
        }
    }
    return ans;
}

function maxProfitRecur(i, jobs, memo) {
    if (i === jobs.length)
        return 0;

    // If value is memoized
    if (memo[i] !== -1)
        return memo[i];

    // Find the next closest job if
    // current job is chosen.
    const next = findNextJob(i, jobs);

    // Find maximum profit if current job
    // is chosen.
    const take
        = jobs[i][2] + maxProfitRecur(next, jobs, memo);

    // Find maximum profit if current
    // job is skipped.
    const noTake = maxProfitRecur(i + 1, jobs, memo);

    memo[i] = Math.max(take, noTake);
    return memo[i];
}

function maxProfit(jobs) {
    jobs.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
    const memo = Array(jobs.length).fill(-1);
    return maxProfitRecur(0, jobs, memo);
}

const jobs = [
    [ 1, 2, 50 ], [ 3, 5, 20 ], [ 6, 19, 100 ],
    [ 2, 100, 200 ]
];
console.log(maxProfit(jobs));

Output
250

Time Complexity: O(nlogn)
Auxilairy Space : O(n)

Comment