# Solution For Employee Free Time

The Employee Free Time problem on LeetCode is a problem that requires finding out time slots during which all employees are free. In this problem, each employee has a list of intervals during which they are busy, and the goal is to find out the list of time slots during which all employees are free.

To solve this problem, we will need to follow these steps:

Step 1: Create a list of all the time intervals during which the employees are busy.

Step 2: Sort the list of intervals by their start time.

Step 3: Merge the overlapping intervals to get a new list of non-overlapping intervals.

Step 4: Identify the gaps between the non-overlapping intervals. These gaps represent the time slots during which all employees are free.

Step 5: Return the list of these gaps.

Let’s look at an example to help us understand how to solve this problem:

Assume we have three employees, each with their busy intervals:

Employee 1: [(1, 3), (6, 7)] Employee 2: [(2, 4)] Employee 3: [(2, 3), (9, 12)]

Step 1: We create a list of all the intervals during which the employees are busy.

[(1, 3), (2, 4), (2, 3), (6, 7), (9, 12)]

Step 2: We sort the list of intervals by their start time.

[(1, 3), (2, 3), (2, 4), (6, 7), (9, 12)]

Step 3: We merge the overlapping intervals to get a new list of non-overlapping intervals.

[(1, 4), (6, 7), (9, 12)]

Step 4: We identify the gaps between the non-overlapping intervals. These gaps represent the time slots during which all employees are free.

Gaps: (4, 6), (7, 9)

Step 5: We return the list of gaps.

[(4, 6), (7, 9)]

Here’s the Python implementation for this approach:

“`
def employeeFreeTime(schedule: List[List[Tuple[int, int]]]) -> List[Tuple[int, int]]:
intervals = [] for employee in schedule:
for interval in employee:
intervals.append(interval)

``````intervals.sort()

merged_intervals = [intervals[0]]
for interval in intervals:
if interval[0] <= merged_intervals[-1][1]:
merged_intervals[-1] = (merged_intervals[-1][0], max(merged_intervals[-1][1], interval[1]))
else:
merged_intervals.append(interval)

free_time = []
for i in range(1, len(merged_intervals)):
free_time.append((merged_intervals[i-1][1], merged_intervals[i][0]))

return free_time
``````

“`

In this approach, we first create a list of all the intervals during which the employees are busy. We then sort this list by start time and merge overlapping intervals to get a new list of non-overlapping intervals. Finally, we find the gaps between the non-overlapping intervals and return them as the list of time slots during which all employees are free.

## Step by Step Implementation For Employee Free Time

`This is a difficult problem that requires understanding of how to use interval trees. I suggest looking up some resources on interval trees and then trying to solve the problem yourself.`
`This is a difficult problem that requires understanding of how to use interval trees. I suggest reading up on interval trees and then trying to solve the problem yourself.`
```/**
* Definition for an interval.
* function Interval(start, end) {
*     this.start = start;
*     this.end = end;
* }
*/
/**
* @param {Interval[][]} schedule
* @return {Interval[]}
*/
var employeeFreeTime = function(schedule) {
// create a min heap to store all the start time of the intervals
let minHeap = new MinHeap(schedule.length * 2);

// create a max heap to store all the end time of the intervals
let maxHeap = new MaxHeap(schedule.length * 2);

// put all the start time and end time into min heap and max heap
for (let i = 0; i < schedule.length; i++) {
for (let j = 0; j < schedule[i].length; j++) {
minHeap.push(schedule[i][j].start);
maxHeap.push(schedule[i][j].end);
}
}

// sort the min heap and max heap
minHeap.sort((a, b) => a - b);
maxHeap.sort((a, b) => b - a);

// create a variable to store the result
let result = [];

// create a variable to store the previous end time
let prevEndTime = null;

// loop through the max heap
while (maxHeap.size() > 0) {
// get the current end time
let currEndTime = maxHeap.pop();

// if the current end time is not the same as the previous end time
// that means there is a gap between the previous end time and current start time
if (currEndTime !== prevEndTime) {
// get the current start time
let currStartTime = minHeap.pop();

// if the current start time is greater than the current end time
// that means there is a gap between the current end time and current start time
// so we add it to the result
if (currStartTime > currEndTime) {
result.push(new Interval(currEndTime, currStartTime));
}

// update the previous end time
prevEndTime = currEndTime;
}
}

return result;
};

// define a min heap
function MinHeap(size) {
this.heap = new Array(size);
this.size = 0;
}

MinHeap.prototype.push = function(num) {
this.heap[this.size] = num;
this.size++;
this.heapifyUp(this.size - 1);
}

MinHeap.prototype.heapifyUp = function(index) {
let curr = index;
let parent = Math.floor((curr - 1) / 2);

while (curr > 0 && this.heap[curr] < this.heap[parent]) {
let temp = this.heap[curr];
this.heap[curr] = this.heap[parent];
this.heap[parent] = temp;

curr = parent;
parent = Math.floor((curr - 1) / 2);
}
}

MinHeap.prototype.sort = function(compare) {
let start = Math.floor((this.size - 2) / 2);

for (let i = start; i >= 0; i--) {
this.heapifyDown(i, this.size, compare);
}
}

MinHeap.prototype.heapifyDown = function(index, size, compare) {
let curr = index;
let left = 2 * curr + 1;
let right = 2 * curr + 2;
let smallest = curr;

if (left < size && compare(this.heap[left], this.heap[smallest]) < 0) {
smallest = left;
}

if (right < size && compare(this.heap[right], this.heap[smallest]) < 0) {
smallest = right;
}

if (smallest !== curr) {
let temp = this.heap[curr];
this.heap[curr] = this.heap[smallest];
this.heap[smallest] = temp;

this.heapifyDown(smallest, size, compare);
}
}

MinHeap.prototype.peek = function() {
if (this.size === 0) {
return null;
}

return this.heap[0];
}

MinHeap.prototype.pop = function() {
if (this.size === 0) {
return null;
}

let result = this.heap[0];
this.heap[0] = this.heap[this.size - 1];
this.size--;
this.heapifyDown(0, this.size, (a, b) => a - b);

return result;
}

MinHeap.prototype.isEmpty = function() {
return this.size === 0;
}

MinHeap.prototype.getSize = function() {
return this.size;
}

// define a max heap
function MaxHeap(size) {
this.heap = new Array(size);
this.size = 0;
}

MaxHeap.prototype.push = function(num) {
this.heap[this.size] = num;
this.size++;
this.heapifyUp(this.size - 1);
}

MaxHeap.prototype.heapifyUp = function(index) {
let curr = index;
let parent = Math.floor((curr - 1) / 2);

while (curr > 0 && this.heap[curr] > this.heap[parent]) {
let temp = this.heap[curr];
this.heap[curr] = this.heap[parent];
this.heap[parent] = temp;

curr = parent;
parent = Math.floor((curr - 1) / 2);
}
}

MaxHeap.prototype.sort = function(compare) {
let start = Math.floor((this.size - 2) / 2);

for (let i = start; i >= 0; i--) {
this.heapifyDown(i, this.size, compare);
}
}

MaxHeap.prototype.heapifyDown = function(index, size, compare) {
let curr = index;
let left = 2 * curr + 1;
let right = 2 * curr + 2;
let largest = curr;

if (left < size && compare(this.heap[left], this.heap[largest]) > 0) {
largest = left;
}

if (right < size && compare(this.heap[right], this.heap[largest]) > 0) {
largest = right;
}

if (largest !== curr) {
let temp = this.heap[curr];
this.heap[curr] = this.heap[largest];
this.heap[largest] = temp;

this.heapifyDown(largest, size, compare);
}
}

MaxHeap.prototype.peek = function() {
if (this.size === 0) {
return null;
}

return this.heap[0];
}

MaxHeap.prototype.pop = function() {
if (this.size === 0) {
return null;
}

let result = this.heap[0];
this.heap[0] = this.heap[this.size - 1];
this.size--;
this.heapifyDown(0, this.size, (a, b) => b - a);

return result;
}

MaxHeap.prototype.isEmpty = function() {
return this.size === 0;
}

MaxHeap.prototype.getSize = function() {
return this.size;
}```
```/**
* Definition for an interval.
* struct Interval {
*     int start;
*     int end;
*     Interval() : start(0), end(0) {}
*     Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
vector employeeFreeTime(vector>& schedule) {
vector res;
// add all intervals to one vector
vector intervals;
for (auto& emp: schedule) {
for (auto& interval: emp) {
intervals.push_back(interval);
}
}
// sort the vector of intervals
sort(intervals.begin(), intervals.end(),
[](Interval& a, Interval& b){return a.start < b.start;});
// find all intervals of free time
int end = intervals[0].end;
for (auto& interval: intervals) {
if (interval.start > end) {
res.push_back(Interval(end, interval.start));
}
end = max(end, interval.end);
}
return res;
}
};```
```/**
* Definition for an interval.
* public class Interval {
*     public int start;
*     public int end;
*     public Interval() { start = 0; end = 0; }
*     public Interval(int s, int e) { start = s; end = e; }
* }
*/
public class Solution {
public IList EmployeeFreeTime(IList> schedule) {
// Initialize result list
List result = new List();

// Base case
if (schedule.Count == 0) {
return result;
}

// Sort the schedule by start time
schedule.OrderBy(s => s.start);

// Get the earliest start time and latest end time
int start = schedule[0][0].start;
int end = schedule[0][0].end;

// Iterate through the schedule
foreach (var item in schedule) {
// If the current start time is before the end time
// we need to update the end time
if (item.start <= end) {
end = Math.Max(end, item.end);
}
// Otherwise, we have found an interval with no
// overlap so we can add it to the result
else {
start = item.start;
end = item.end;
}
}

// Add the last interval to the result