Employee Free Time
You’re given a list containing the schedules of multiple employees. Each person’s schedule is a list of non-overlapping intervals in sorted order. An interval is specified with the start and end time, both being positive integers. Your task is to find the list of finite intervals representing the free time for all the employees.
You’re given a list containing the schedules of multiple employees. Each person’s schedule is a list of non-overlapping intervals in sorted order. An interval is specified with the start and end time, both being positive integers. Your task is to find the list of finite intervals representing the free time for all the employees.
Constraints
- 1 ≤
schedule.length,schedule[i].length≤ 50 - 0 ≤
interval.start<interval.end≤ 10⁸, whereintervalis any interval in the list of schedules.
Examples
Example 1
Input:
schedule = [[[1, 3], [6, 7]], [[2, 4]], [[2, 5], [9, 12]]]
Explanation:
Combining all intervals: [1, 3], [6, 7], [2, 4], [2, 5], [9, 12].
Merging overlapping intervals gives busy periods: [1, 5], [6, 7], [9, 12].
The gaps between these busy periods (excluding the very start and end) represent free time.
Output: [[5, 6], [7, 9]]
Example 2
Input:
schedule = [[[1, 2], [5, 6]], [[1, 3]], [[4, 10]]]
Explanation:
Combining all intervals: [1, 2], [5, 6], [1, 3], [4, 10].
Merging overlapping intervals gives busy periods: [1, 3], [4, 10].
The gap between these busy periods represents free time.
Output: [[3, 4]]
Solution
We'll start by flattering all the intervals provided, after that I'll sort them to combine all the overlapping intervals. Now I'll have busyTime of all the employees, Freetime is gap between all the busytime intervals.
function EmployeeFreetime(intervals){
let combinedIntervals=[]
for(let i=0; i<intervals.length; i++){
combinedIntervals.push(...intervals[i])
}
let sortedCombinedIntervals=combinedIntervals.sort((a,b)=>a[0]-b[0]);
let busyTime=[sortedCombinedIntervals[0]];
for(let i=1; i<sortedCombinedIntervals.length; i++){
let lastEntry= busyTime[busyTime.length-1];
if(lastEntry[1]>=sortedCombinedIntervals[i][0]){
busyTime[busyTime.length-1][1]=Math.max(lastEntry[1], sortedCombinedIntervals[i][1])
}else{
busyTime.push(sortedCombinedIntervals[i])
}
}
let freeTime=[];
for (let i=0; i<busyTime.length; i++){
if(i+1<busyTime.length){
let curr=busyTime[i];
let next = busyTime[i+1];
freeTime.push([curr[1],next[0]])
}
}
return freeTime
}
console.log(EmployeeFreetime( [
[[1, 3], [6, 7]], [[2, 4]], [[2, 5], [9, 12]]]))
or Little clean solution
function employeeFreeTime(schedules) {
// 1. Flatten everyone's intervals into a single array (without mutating originals)
const allIntervals = schedules.flatMap(employeeIntervals =>
employeeIntervals.map(([start, end]) => [start, end])
);
if (allIntervals.length === 0) return [];
// 2. Sort intervals by start time
allIntervals.sort((a, b) => a[0] - b[0]);
// 3. Merge overlapping/touching intervals into busy blocks
const mergedBusyTimes = [allIntervals[0]];
for (let i = 1; i < allIntervals.length; i++) {
const [start, end] = allIntervals[i];
const lastMerged = mergedBusyTimes[mergedBusyTimes.length - 1];
if (start <= lastMerged[1]) {
// Overlaps with the last merged block -> extend it
lastMerged[1] = Math.max(lastMerged[1], end);
} else {
// No overlap -> start a new busy block
mergedBusyTimes.push([start, end]);
}
}
// 4. Gaps between consecutive busy blocks are the free time
const freeTime = [];
for (let i = 0; i < mergedBusyTimes.length - 1; i++) {
const currentEnd = mergedBusyTimes[i][1];
const nextStart = mergedBusyTimes[i + 1][0];
freeTime.push([currentEnd, nextStart]);
}
return freeTime;
}
console.log(employeeFreeTime([
[[1, 3], [6, 7]],
[[2, 4]],
[[2, 5], [9, 12]]
]));
// -> [[5, 6], [7, 9]]