Someone asked me this question:
You are given a list of intervals. You have to design an algorithm to find the sequence of non-overlapping intervals so that the sum of the range of intervals is maximum.
For Example:
If given intervals are:
["06:00","08:30"],
["09:00","11:00"],
["08:00","09:00"],
["09:00","11:30"],
["10:30","14:00"],
["12:00","14:00"]
Range is maximized when three intervals
[“06:00”, “08:30”],
[“09:00”, “11:30”],
[“12:00”, “14:00”],
are chosen.
Therefore, the answer is 420 (minutes).
This is a standard interval scheduling problem.
It can be solved by using dynamic programming.
Algorithm
Let there be n
intervals. sum[i]
stores maximum sum of interval up to interval i
in sorted interval array. The algorithm is as follows
Sort the intervals in order of their end timings.
sum[0] = 0
For interval i from 1 to n in sorted array
j = interval in 1 to i-1 whose endtime is less than beginning time of interval i.
If j exist, then sum[i] = max(sum[j]+duration[i],sum[i-1])
else sum[i] = max(duration[i],sum[i-1])
The iteration goes for n
steps and in each step, j
can be found using binary search, i.e. in log n
time.
Hence algorithm takes O(n log n)
time.
public int longestNonOverLappingTI(TimeInterval[] tis){
Arrays.sort(tis);
int[] mt = new int[tis.length];
mt[0] = tis[0].getTime();
for(int j=1;j<tis.length;j++){
for(int i=0;i<j;i++){
int x = tis[j].overlaps(tis[i])?tis[j].getTime():mt[i] + tis[j].getTime();
mt[j] = Math.max(x,mt[j]);
}
}
return getMax(mt);
}
public class TimeInterval implements Comparable <TimeInterval> {
public int start;
public int end;
public TimeInterval(int start,int end){
this.start = start;
this.end = end;
}
public boolean overlaps(TimeInterval that){
return !(that.end < this.start || this.end < that.start);
}
public int getTime(){
return end - start;
}
@Override
public int compareTo(TimeInterval timeInterval) {
if(this.end < timeInterval.end)
return -1;
else if( this.end > timeInterval.end)
return 1;
else{
//end timeIntervals are same
if(this.start < timeInterval.start)
return -1;
else if(this.start > timeInterval.start)
return 1;
else
return 0;
}
}
}
Heres the working code. Basically this runs in O(n^2) because of the two for loops. But as Shashwat said there are ways to make it run in O(n lg n)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With