The problem requires finding the maximum profit from scheduling non-overlapping
jobs.
Key observations are that we need to
sort jobs by end time
to
efficiently find non-overlapping ones and use
dynamic programming
to
store intermediate results.
For each job, we decide whether to
include it
(plus profit
from last non-overlapping job) or
exclude it
(carry forward
previous profit). Here,
binary search
helps
quickly find the latest non-overlapping job.
class Solution { public: struct Job{ int startTime; int endTime; int profit; }; static bool cmp(Job j1, Job j2){ return j1.endTime < j2.endTime; } // Will use binary search to find the non overlapping job // Returns the latest job that ends before the current job starts. int srch(vector<Job> &vJobs, int idx){ int start = 0; int end = idx-1; // As it is 0-based indexing i.e why end=idx-1 int ans = -1; while(start<=end){ int mid = (start+end)/2; // Compare endTime of mid with the startTime of element present idx position if(vJobs[mid].endTime <= vJobs[idx].startTime){ start = mid+1; ans = mid; } else end = mid-1; } return ans; } int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) { int noOfJobs = startTime.size(); vector<Job> vJobs; for(int i=0;i<noOfJobs;i++) vJobs.push_back({startTime[i],endTime[i],profit[i]}); // Sorting by endTime ensures that for any Job i, all possible non-overlapping // jobs (ending before ith job) appear before it in sorted order. sort(vJobs.begin(),vJobs.end(),cmp); int ans[noOfJobs+1]; // ans[i] tells given i jobs, what maximum profit you can make. // If there are no jobs, then maxProfit = 0 ans[0]=0; for(int i=1;i<=noOfJobs;i++){ int include = vJobs[i-1].profit; int prevNonOverlappingJob = srch(vJobs,i-1); // As prevNonOverlappingJob idx will come as zero based. Therefore, dp state // corresponding to it will be represented by t[prevNonOverlappingJob+1]; if(prevNonOverlappingJob!=-1) include += ans[prevNonOverlappingJob+1]; int exclude = ans[i-1]; ans[i] = max(include,exclude); } return ans[noOfJobs]; } }; /* Golden Note: 1. Sort by endTime when we need to efficiently find the latest non-overlapping event. 2. Sort by startTime when we merge intervals or checking overlaps. */
Sorting takes O(n log n) time and each binary search operation takes O(log n) time for n jobs.
We use O(n) space to store the jobs and the DP array.