Given an array of jobs with different time requirements, where each job consists of start time, end time and CPU load.
The task is to find the maximum CPU load at any time if all jobs are running on the same machine.
Examples:
Input: jobs[] = {{1, 4, 3}, {2, 5, 4}, {7, 9, 6}}
Output: 7
Explanation:
In the above-given jobs, there are two jobs which overlaps.
That is, Job [1, 4, 3] and [2, 5, 4] overlaps for the time period in [2, 4]
Hence, the maximum CPU Load at this instant will be maximum (3 + 4 = 7).
Input: jobs[] = {{6, 7, 10}, {2, 4, 11}, {8, 12, 15}}
Output: 15
Explanation:
Since, There are no jobs that overlaps.
Maximum CPU Load will be - max(10, 11, 15) = 15
This problem is generally the application of the Merge Intervals.
Approach: The idea is to maintain min-heap for the jobs on the basis of their end times. Then, for each instance find the jobs which are complete and remove them from the Min-heap. That is, Check that the end-time of the jobs in the min-heap had ended before the start time of the current job. Also at each instance, find the maximum CPU Load on the machine by taking the sum of all the jobs that are present in the min-heap.
For Example:
Given Jobs be {{1, 4, 3}, {2, 5, 4}, {7, 9, 6}}
Min-Heap - {}
Instance 1:
The job {1, 4, 3} is inserted into the min-heap
Min-Heap - {{1, 4, 3}},
Total CPU Load = 3
Instance 2:
The job {2, 5, 4} is inserted into the min-heap.
While the job {1, 4, 3} is still in the CPU,
because end-time of Job 1 is greater than
the start time of the new job {2, 5, 4}.
Min-Heap - {{1, 4, 3}, {2, 5, 4}}
Total CPU Load = 4 + 3 = 7
Instance 3:
The job {7, 9, 6} is inserted into the min-heap.
After popping up all the other jobs because their
end time is less than the start time of the new job
Min Heap - {7, 9, 6}
Total CPU Load = 6
Maximum CPU Load = max(3, 7, 6) = 7
Below is the implementation of the above approach:
C++
// C++ implementation to find the
// maximum CPU Load from the given
// lists of the jobs
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
// Blueprint of the job
class Job {
public:
int start = 0;
int end = 0;
int cpuLoad = 0;
// Constructor function for
// the CPU Job
Job(int start, int end, int cpuLoad)
{
this->start = start;
this->end = end;
this->cpuLoad = cpuLoad;
}
};
class MaximumCPULoad {
// Structure to compare two
// CPU Jobs by their end time
public:
struct endCompare {
bool operator()(const Job& x, const Job& y)
{
return x.end > y.end;
}
};
// Function to find the maximum
// CPU Load at any instance of
// the time for given jobs
static int findMaxCPULoad(vector<Job>& jobs)
{
// Condition when there are
// no jobs then CPU Load is 0
if (jobs.empty()) {
return 0;
}
// Sorting all the jobs
// by their start time
sort(jobs.begin(), jobs.end(),
[](const Job& a, const Job& b) {
return a.start < b.start;
});
int maxCPULoad = 0;
int currentCPULoad = 0;
// Min-heap implemented using the
// help of the priority queue
priority_queue<Job, vector<Job>, endCompare>
minHeap;
// Loop to iterate over all the
// jobs from the given list
for (auto job : jobs) {
// Loop to remove all jobs from
// the heap which is ended
while (!minHeap.empty()
&& job.start > minHeap.top().end) {
currentCPULoad -= minHeap.top().cpuLoad;
minHeap.pop();
}
// Add the current Job to CPU
minHeap.push(job);
currentCPULoad += job.cpuLoad;
maxCPULoad = max(maxCPULoad, currentCPULoad);
}
return maxCPULoad;
}
};
// Driver Code
int main(int argc, char* argv[])
{
vector<Job> input
= { { 1, 4, 3 }, { 7, 9, 6 }, { 2, 5, 4 } };
cout << "Maximum CPU load at any time: "
<< MaximumCPULoad::findMaxCPULoad(input) << endl;
}
Java
import java.util.*;
class Job {
int start;
int end;
int cpuLoad;
public Job(int start, int end, int cpuLoad) {
this.start = start;
this.end = end;
this.cpuLoad = cpuLoad;
}
};
class MaximumCPULoad {
public static int findMaxCPULoad(List<Job> jobs)
{
// sort the jobs by start time
Collections.sort(jobs, (a, b) -> Integer.compare(a.start, b.start));
int maxCPULoad = 0;
int currentCPULoad = 0;
PriorityQueue<Job> minHeap = new PriorityQueue<>(jobs.size(),
(a, b) -> Integer.compare(a.end, b.end));
for (Job job : jobs) {
// remove all jobs that have ended
while (!minHeap.isEmpty() && job.start > minHeap.peek().end)
currentCPULoad -= minHeap.poll().cpuLoad;
// add the current job into the minHeap
minHeap.offer(job);
currentCPULoad += job.cpuLoad;
maxCPULoad = Math.max(maxCPULoad, currentCPULoad);
}
return maxCPULoad;
}
public static void main(String[] args) {
List<Job> input = new ArrayList<Job>(Arrays.asList(new Job(1, 4, 3),
new Job(2, 5, 4),
new Job(7, 9, 6)));
System.out.println("Maximum CPU load at any time: " +
MaximumCPULoad.findMaxCPULoad(input));
input = new ArrayList<Job>(Arrays.asList(new Job(6, 7, 10), new Job(2, 4, 11), new Job(8, 12, 15)));
System.out.println("Maximum CPU load at any time: " +
MaximumCPULoad.findMaxCPULoad(input));
}
}
// This code is contributed by mohan kumar 6.
Python3
# Python implementation to find the
# maximum CPU Load from the given
# lists of the jobs
from heapq import *
# Blueprint of the job
class job:
# Constructor of the Job
def __init__(self, start,
end, cpu_load):
self.start = start
self.end = end
self.cpu_load = cpu_load
# Operator overloading for the
# Object that is Job
def __lt__(self, other):
# min heap based on job.end
return self.end < other.end
# Function to find the maximum
# CPU Load for the given list of jobs
def find_max_cpu_load(jobs):
# Sort the jobs by start time
jobs.sort(key=lambda x: x.start)
max_cpu_load, current_cpu_load = 0, 0
# Min-Heap
min_heap = []
# Loop to iterate over the list
# of the jobs given for the CPU
for j in jobs:
# Remove all the jobs from
# the min-heap which ended
while(len(min_heap) > 0 and
j.start >= min_heap[0].end):
current_cpu_load -= min_heap[0].cpu_load
heappop(min_heap)
# Add the current job
# into min_heap
heappush(min_heap, j)
current_cpu_load += j.cpu_load
max_cpu_load = max(max_cpu_load,
current_cpu_load)
return max_cpu_load
# Driver Code
if __name__ == "__main__":
jobs = [job(1, 4, 3), job(2, 5, 4),
job(7, 9, 6)]
print("Maximum CPU load at any time: " +
str(find_max_cpu_load(jobs)))
C#
// C# implementation to find the
// maximum CPU Load from the given
// lists of the jobs
using System;
using System.Collections.Generic;
using System.Linq;
// Blueprint of the job
public class Job {
public int Start { get; set; }
public int End { get; set; }
public int CpuLoad { get; set; }
// Constructor function for the CPU Job
public Job(int start, int end, int cpuLoad) {
Start = start;
End = end;
CpuLoad = cpuLoad;
}
}
public class MaximumCpuLoad {
// Structure to compare two CPU Jobs by their end time
public class EndCompare : IComparer<Job> {
public int Compare(Job x, Job y) {
return x.End.CompareTo(y.End);
}
}
// Function to find the maximum CPU Load at any instance of the time for given jobs
public static int FindMaxCpuLoad(List<Job> jobs) {
// Condition when there are no jobs then CPU Load is 0
if (jobs.Count == 0) {
return 0;
}
// Sorting all the jobs by their start time
jobs = jobs.OrderBy(j => j.Start).ToList();
int maxCpuLoad = 0;
int currentCpuLoad = 0;
// Min-heap implemented using the help of the SortedSet
var minHeap = new SortedSet<Job>(new EndCompare());
// Loop to iterate over all the jobs from the given list
foreach (var job in jobs) {
// Loop to remove all jobs from the heap which is ended
while (minHeap.Count > 0 && job.Start > minHeap.First().End) {
currentCpuLoad -= minHeap.First().CpuLoad;
minHeap.Remove(minHeap.First());
}
// Add the current Job to CPU
minHeap.Add(job);
currentCpuLoad += job.CpuLoad;
maxCpuLoad = Math.Max(maxCpuLoad, currentCpuLoad);
}
return maxCpuLoad;
}
}
// Driver Code
public class Program {
public static void Main(string[] args) {
var input = new List<Job> {
new Job(1, 4, 3),
new Job(7, 9, 6),
new Job(2, 5, 4)
};
Console.WriteLine("Maximum CPU load at any time: {0}", MaximumCpuLoad.FindMaxCpuLoad(input));
}
}
// This code is contributed by rutikbhosale.
JavaScript
class Job {
constructor(start, end, cpuLoad) {
this.start = start;
this.end = end;
this.cpuLoad = cpuLoad;
}
};
class MaximumCPULoad
{
static findMaxCPULoad(jobs)
{
// sort the jobs by start time
jobs.sort((a, b) => a.start - b.start);
let maxCPULoad = 0;
let currentCPULoad = 0;
const minHeap = [];
for (const job of jobs) {
// remove all jobs that have ended
while (minHeap.length > 0 && job.start > minHeap[0].end) {
currentCPULoad -= minHeap.shift().cpuLoad;
}
// add the current job into the minHeap
minHeap.push(job);
currentCPULoad += job.cpuLoad;
maxCPULoad = Math.max(maxCPULoad, currentCPULoad);
}
return maxCPULoad;
}
}
const input = [new Job(1, 4, 3), new Job(2, 5, 4), new Job(7, 9, 6)];
console.log("Maximum CPU load at any time: " + MaximumCPULoad.findMaxCPULoad(input));
// This code is contributed by anskalyan3.
OutputMaximum CPU load at any time: 7
Performance Analysis:
- Time complexity: O(N*logN)
- Auxiliary Space: O(N)
Approach 2:
The idea is simple. We have supposed n intervals, so we have 2n endpoints ( here endpoint is the end of an interval and its value is the time associated with it). We can take an endpoint and combine it with its load value associated with it and with a flag which states whether it is a starting point or ending point of an interval. Then we can just sort the endpoints in increasing order(if there is a tie in value of endpoints then we will break the tie by putting the endpoint which is starting at first place as compared to the endpoint which is ending; if both the endpoints are starting or ending then we will break the tie arbitrarily).
After sorting, we will proceed through the endpoints using for loop. And if we have an endpoint that is the starting point of an interval then we will add the load value associated with it in a variable say, count. We will also take the maximum of the count values and store it in a variable called result.
But when we get an endpoint that is ending then we will decrease the load value associated with it from the count.
At the end, we will return the result.
Lets take an example: suppose the jobs are {1, 4, 3}, {2, 5, 4}, {7, 9, 6}.
our sorted endpoints will be 1(start), 2(start), 4(end), 5(end), 7(start), 9(end) .
and the corresponding loads will be 3, 4, 3, 4, 6, 6.
start traversing the endpoints:
so after traversing first endpoint which is 1(start) we have count+=3 (here 3 is the load associated with it) so count =3. Since the 1 is starting point so we will update the result. So result=max(result,count) so, result=3.
After traversing 2(start) we have count+=4, so count=7, result=max(result,count)=7.
After traversing 4(end) we have count-=3(we have subtracted because it is ending point) so count=4. result will not be updated since we are decreasing the count.
After traversing 5(end) we have count-=4 so count=0.
After traversing 7(start) we have count+=6 so count=6, result=max(result,count)=7.
After traversing 9(end) we have count-=6 so count=0.
Our result will be 7.
C++14
// C++ implementation to find the
// maximum CPU Load from the given array of jobs
#include <bits/stdc++.h>
using namespace std;
// the job struct will have s(starting time) , e(ending time) , load(cpu load)
struct Job {
int s, e, load;
};
// endpoint struct will have val(the time associated with the endpoint),
// load(cpu load associated with the endpoint),
// a flag isStart which will tell if the endpoint is starting or ending point of
// an interval
struct Endpoint {
int val, load;
bool isStart;
};
// custom comparator function which is used by the c++ sort stl
bool comp(const Endpoint& a, const Endpoint& b) {
if (a.val != b.val)
return a.val < b.val;
return a.isStart == true && b.isStart == false;
}
//function to find maximum cpu load
int maxCpuLoad(vector<Job> v)
{
int count = 0; // count will contain the count of current loads
int result = 0; // result will contain maximum of all counts
// this data array will contain all the endpoints combined with their load values
// and flags telling whether they are starting or ending point
vector<Endpoint> data;
for (int i = 0; i < v.size(); i++) {
data.emplace_back(Endpoint{ v[i].s, v[i].load, true});
data.emplace_back(Endpoint{ v[i].e, v[i].load, false});
}
sort(data.begin(), data.end(), comp);
for (int i = 0; i < data.size(); i++) {
if (data[i].isStart == true) {
count += data[i].load;
result = max(result, count);
}
else
count -= data[i].load;
}
return result;
}
//Driver code to test maxCpuLoad function
int main() {
vector<Job> v = {
{6, 7, 10},
{2, 4, 11},
{8, 12, 15}
};
cout << maxCpuLoad(v);
return 0;
}
// this code is contributed by Mohit Puri
Java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class Job {
int s, e, load;
public Job(int s, int e, int load) {
this.s = s;
this.e = e;
this.load = load;
}
}
class Endpoint implements Comparable<Endpoint> {
int val, load;
boolean isStart;
public Endpoint(int val, int load, boolean isStart) {
this.val = val;
this.load = load;
this.isStart = isStart;
}
public int compareTo(Endpoint other) {
if (this.val != other.val) {
return Integer.compare(this.val, other.val);
}
if (this.isStart && !other.isStart) {
return -1;
}
if (!this.isStart && other.isStart) {
return 1;
}
return 0;
}
}
class Main {
static int maxCpuLoad(List<Job> jobs) {
int count = 0;
int result = 0;
List<Endpoint> data = new ArrayList<>();
for (Job job : jobs) {
data.add(new Endpoint(job.s, job.load, true));
data.add(new Endpoint(job.e, job.load, false));
}
Collections.sort(data);
for (Endpoint endpoint : data) {
if (endpoint.isStart) {
count += endpoint.load;
result = Math.max(result, count);
} else {
count -= endpoint.load;
}
}
return result;
}
public static void main(String[] args) {
List<Job> jobs = new ArrayList<>();
jobs.add(new Job(6, 7, 10));
jobs.add(new Job(2, 4, 11));
jobs.add(new Job(8, 12, 15));
System.out.println(maxCpuLoad(jobs));
}
}
Python3
# Python3 implementation to find the
# maximum CPU Load from the given array of jobs
# the job struct will have s(starting time) , e(ending time) , load(cpu load)
class Job:
def __init__(self,s,e,l) -> None:
self.s =s; self.e =e; self.load = l
# endpoint will have val(the time associated with the endpoint),
# load(cpu load associated with the endpoint),
# a flag isStart which will tell if the endpoints starting or ending point
# an interval
class Endpoint:
def __init__(self, v=0, l=0, isStart=False) -> None:
self.val = v
self.load = l
self.isStart = isStart
def __lt__(self, other):
if self.val != other.val:
return self.val < other.val
return self.isStart == True and other.isStart == False
# function to find maximum cpu load
def maxCpuLoad(v):
count = 0 # count will contain the count of current loads
result = 0 # result will contain maximum of all counts
# this data array will contain all the endpoints combined with their load values
# and flags telling whether they are starting or ending point
data = []
for i in range(len(v)):
data.append(Endpoint(v[i].s, v[i].load, True))
data.append(Endpoint(v[i].e, v[i].load, False))
data.sort()
for i in range(len(data)):
if data[i].isStart == True:
count += data[i].load
result = max(result, count)
else:
count -= data[i].load
return result
# Driver code to test maxCpuLoad function
if __name__ == "__main__":
v = [Job(6, 7, 10), Job(2, 4, 11), Job(8, 12, 15)]
print(maxCpuLoad(v))
C#
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
// C# implementation to find the
// maximum CPU Load from the given array of jobs
// the job struct will have s(starting time) , e(ending time) , load(cpu load)
class Job {
public int s;
public int e;
public int load;
public Job(int x, int y, int z){
s = x;
y = e;
load = z;
}
}
// endpoint struct will have val(the time associated with the endpoint),
// load(cpu load associated with the endpoint),
// a flag isStart which will tell if the endpoint is starting or ending point of
// an interval
class Endpoint {
public int val;
public int load;
public bool isStart;
public Endpoint(int x, int y, bool z){
val = x;
load = y;
isStart = z;
}
}
class HelloWorld {
// custom sort function.
class GFG : IComparer<Endpoint>
{
public int Compare(Endpoint a, Endpoint b)
{
if (a.val != b.val){
if(a.val < b.val) return 1;
else return 0;
}
// CompareTo() method
if(a.isStart == true && b.isStart == false) return 1;
return 0;
}
}
//function to find maximum cpu load
public static int maxCpuLoad(Job[] v)
{
int count = 0; // count will contain the count of current loads
int result = 0; // result will contain maximum of all counts
// this data array will contain all the endpoints combined with their load values
// and flags telling whether they are starting or ending point
List<Endpoint> data = new List<Endpoint>();
for (int i = 0; i < v.Length; i++) {
data.Add(new Endpoint(v[i].s, v[i].load, true));
data.Add(new Endpoint(v[i].e, v[i].load, false));
}
GFG gg = new GFG();
data.Sort(gg);
for (int i = 0; i < data.Count; i++) {
if (data[i].isStart == true) {
count += data[i].load;
result = Math.Max(result, count);
}
else
count -= data[i].load;
}
return result;
}
static void Main() {
Job[] v = new Job[3];
v[0] = new Job(6, 7, 10);
v[1] = new Job(2, 4, 11);
v[2] = new Job(8, 12, 15);
Console.WriteLine(maxCpuLoad(v));
}
}
// The code is contributed by Nidhi goel.
JavaScript
<script>
// JavaScript implementation to find the
// maximum CPU Load from the given array of jobs
// the job struct will have s(starting time) , e(ending time) , load(cpu load)
class Job{
constructor(s,e,l){
this.s = s; this.e = e; this.load = l
}
}
// endpoint will have val(the time associated with the endpoint),
// load(cpu load associated with the endpoint),
// a flag isStart which will tell if the endpoints starting or ending point
// an interval
class Endpoint{
constructor(v = 0, l = 0, isStart = false){
this.val = v
this.load = l
this.isStart = isStart
}
}
function comp(a, b) {
if (a.val != b.val)
return a.val - b.val;
return a.isStart == true && b.isStart == false;
}
// function to find maximum cpu load
function maxCpuLoad(v){
let count = 0 // count will contain the count of current loads
let result = 0 // result will contain maximum of all counts
// this data array will contain all the endpoints combined with their load values
// and flags telling whether they are starting or ending point
let data = []
for(let i = 0; i < v.length; i++){
data.push(new Endpoint(v[i].s, v[i].load, true))
data.push(new Endpoint(v[i].e, v[i].load, false))
}
data.sort(comp)
for(let i = 0; i < data.length; i++)
{
if(data[i].isStart == true){
count += data[i].load
result = Math.max(result, count)
}
else
count -= data[i].load
}
return result
}
// Driver code to test maxCpuLoad function
let v = [new Job(6, 7, 10), new Job(2, 4, 11), new Job(8, 12, 15)]
document.write(maxCpuLoad(v),"</br>")
// This code is contributed by shinjanpatra
</script>
Time Complexity: O(nlogn) for sorting the data array.
Auxiliary Space: O(n) which is the size of the data array
Similar Reads
Maximum items that can be filled in K Knapsacks of given Capacity Given an integer array W[] consisting of weights of items and 'K' knapsacks of capacity 'C', find maximum weight we can put in the knapsacks if breaking of an item is not allowed. Examples: Input : w[] = {3, 9, 8}, k = 1, c = 11 Output : 11 The required subset will be {3, 8} where 3+8 = 11 Input : w
11 min read
Maximize total count from the given Array Given an array nums of length N which contains two types of numbers, one which has the value zero, the second which is a positive integer, the task is to collect numbers from the below operations and return the maximum value you can collect. If the given number is a positive integer, then it's your
11 min read
Minimum days to perform all jobs in the given order Given a positive integer array jobs[] and positive integer K, jobs[i] represent the type of the ith job and K represents the minimum number of days that must pass before another job of the same type can be performed. The task is to find the minimum number of days needed to complete all jobs in the s
9 min read
Find minimum time to finish all jobs with given constraints Given an array job[], where each element represents the time required to complete a specific job. There are k identical assignees available to complete these jobs, and each assignee takes t units of time to complete one unit of a job. The task is to determine the minimum time required to complete al
11 min read
Maximize jobs that can be completed under given constraint Given an integer N denoting number of jobs and a matrix ranges[] consisting of a range [start day, end day] for each job within which it needs to be completed, the task is to find the maximum possible jobs that can be completed.Examples: Input: N = 5, Ranges = {{1, 5}, {1, 5}, {1, 5}, {2, 3}, {2, 3}
8 min read