🧠
Sorting + Min Heap to Track Overlaps
💡 This approach improves efficiency by sorting jobs and using a min heap to track currently running jobs, avoiding checking all pairs.
Intuition
Sort jobs by start time. Use a min heap to keep track of jobs that are currently running (by their end time). Remove jobs that ended before current job starts. Sum loads of jobs in heap to find max load.
Algorithm
- Sort jobs by start time
- Initialize a min heap to store jobs by end time
- Initialize current_load and max_load to 0
- For each job in sorted order:
- Remove all jobs from heap that ended before current job starts, subtract their loads
- Add current job to heap and add its load to current_load
- Update max_load if current_load is greater
💡 The heap helps efficiently remove jobs that no longer overlap, so we only sum loads of overlapping jobs.
import heapq
def find_max_cpu_load(jobs):
jobs.sort(key=lambda x: x[0])
min_heap = [] # stores (end_time, load)
current_load = 0
max_load = 0
for job in jobs:
start, end, load = job
while min_heap and min_heap[0][0] <= start:
ended_job = heapq.heappop(min_heap)
current_load -= ended_job[1]
heapq.heappush(min_heap, (end, load))
current_load += load
max_load = max(max_load, current_load)
return max_load
# Driver code
if __name__ == '__main__':
jobs = [[1,4,3], [2,5,4], [7,9,6]]
print(find_max_cpu_load(jobs)) # Output: 7
Line Notes
jobs.sort(key=lambda x: x[0])Sort jobs by start time to process in chronological order
min_heap = []Min heap to track jobs by their end time for efficient removal
while min_heap and min_heap[0][0] <= start:Remove all jobs that ended before current job starts
ended_job = heapq.heappop(min_heap)Pop the earliest ending job from heap
current_load -= ended_job[1]Subtract load of ended job from current load
heapq.heappush(min_heap, (end, load))Add current job to heap
current_load += loadAdd current job's load to current load
max_load = max(max_load, current_load)Update max load if current load is higher
import java.util.*;
public class MaxCPULoad {
public static int findMaxCPULoad(int[][] jobs) {
Arrays.sort(jobs, (a, b) -> Integer.compare(a[0], b[0]));
PriorityQueue<int[]> minHeap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
int currentLoad = 0, maxLoad = 0;
for (int[] job : jobs) {
int start = job[0], end = job[1], load = job[2];
while (!minHeap.isEmpty() && minHeap.peek()[0] <= start) {
currentLoad -= minHeap.poll()[1];
}
minHeap.offer(new int[]{end, load});
currentLoad += load;
maxLoad = Math.max(maxLoad, currentLoad);
}
return maxLoad;
}
public static void main(String[] args) {
int[][] jobs = {{1,4,3}, {2,5,4}, {7,9,6}};
System.out.println(findMaxCPULoad(jobs)); // Output: 7
}
}
Line Notes
Arrays.sort(jobs, (a, b) -> Integer.compare(a[0], b[0]));Sort jobs by start time
PriorityQueue<int[]> minHeap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));Min heap to track jobs by end time
while (!minHeap.isEmpty() && minHeap.peek()[0] <= start) {Remove jobs that ended before current job starts
currentLoad -= minHeap.poll()[1];Subtract load of ended job
minHeap.offer(new int[]{end, load});Add current job to heap
currentLoad += load;Add current job's load
maxLoad = Math.max(maxLoad, currentLoad);Update max load if current load is higher
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int findMaxCPULoad(vector<vector<int>>& jobs) {
sort(jobs.begin(), jobs.end(), [](auto& a, auto& b) { return a[0] < b[0]; });
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> minHeap; // (end, load)
int currentLoad = 0, maxLoad = 0;
for (auto& job : jobs) {
int start = job[0], end = job[1], load = job[2];
while (!minHeap.empty() && minHeap.top().first <= start) {
currentLoad -= minHeap.top().second;
minHeap.pop();
}
minHeap.push({end, load});
currentLoad += load;
maxLoad = max(maxLoad, currentLoad);
}
return maxLoad;
}
int main() {
vector<vector<int>> jobs = {{1,4,3}, {2,5,4}, {7,9,6}};
cout << findMaxCPULoad(jobs) << endl; // Output: 7
return 0;
}
Line Notes
sort(jobs.begin(), jobs.end(), [](auto& a, auto& b) { return a[0] < b[0]; });Sort jobs by start time
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> minHeap;Min heap to track jobs by end time
while (!minHeap.empty() && minHeap.top().first <= start) {Remove jobs that ended before current job starts
currentLoad -= minHeap.top().second;Subtract load of ended job
minHeap.pop();Remove ended job from heap
minHeap.push({end, load});Add current job to heap
currentLoad += load;Add current job's load
maxLoad = max(maxLoad, currentLoad);Update max load if current load is higher
class MinHeap {
constructor() {
this.heap = [];
}
swap(i, j) {
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
}
parent(i) { return Math.floor((i - 1) / 2); }
left(i) { return 2 * i + 1; }
right(i) { return 2 * i + 2; }
push(val) {
this.heap.push(val);
let i = this.heap.length - 1;
while (i > 0 && this.heap[this.parent(i)][0] > this.heap[i][0]) {
this.swap(i, this.parent(i));
i = this.parent(i);
}
}
pop() {
if (this.heap.length === 1) return this.heap.pop();
const root = this.heap[0];
this.heap[0] = this.heap.pop();
this.heapify(0);
return root;
}
heapify(i) {
let smallest = i;
const left = this.left(i);
const right = this.right(i);
if (left < this.heap.length && this.heap[left][0] < this.heap[smallest][0]) smallest = left;
if (right < this.heap.length && this.heap[right][0] < this.heap[smallest][0]) smallest = right;
if (smallest !== i) {
this.swap(i, smallest);
this.heapify(smallest);
}
}
peek() {
return this.heap[0];
}
size() {
return this.heap.length;
}
}
function findMaxCPULoad(jobs) {
jobs.sort((a, b) => a[0] - b[0]);
const minHeap = new MinHeap();
let currentLoad = 0, maxLoad = 0;
for (const [start, end, load] of jobs) {
while (minHeap.size() > 0 && minHeap.peek()[0] <= start) {
currentLoad -= minHeap.pop()[1];
}
minHeap.push([end, load]);
currentLoad += load;
maxLoad = Math.max(maxLoad, currentLoad);
}
return maxLoad;
}
// Driver code
const jobs = [[1,4,3], [2,5,4], [7,9,6]];
console.log(findMaxCPULoad(jobs)); // Output: 7
Line Notes
jobs.sort((a, b) => a[0] - b[0]);Sort jobs by start time
const minHeap = new MinHeap();Initialize min heap to track jobs by end time
while (minHeap.size() > 0 && minHeap.peek()[0] <= start) {Remove jobs that ended before current job starts
currentLoad -= minHeap.pop()[1];Subtract load of ended job
minHeap.push([end, load]);Add current job to heap
currentLoad += load;Add current job's load
maxLoad = Math.max(maxLoad, currentLoad);Update max load if current load is higher
Sorting takes O(n log n). Each job is pushed and popped at most once from the heap, each operation O(log n).
💡 For n=100000, this approach is efficient enough to run quickly.
Interview Verdict: Accepted and efficient for large inputs
This approach balances clarity and efficiency, suitable for interviews.