LeetCode – Meeting Rooms II (Java)

Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] find the minimum number of conference rooms required.

Java Solution
When a room is taken, the room can not be used for anther meeting until the current meeting is over. As soon as the current meeting is finished, the room can be used for another meeting. We can sort the meetings by start timestamps and sequentially assign each meeting to a room. Each time when we assign a room for a meeting, we check if any meeting is finished so that the room can be reused. In order to efficiently track the earliest ending meeting, we can use a min heap. Whenever an old meeting ends before a new meeting starts, we reuse the room (i.e., do not add more room). Otherwise, we need an extra room (i.e., add a room).

The time complexity is O(N*log(N)).

public int minMeetingRooms(int[][] intervals) {
    Arrays.sort(intervals, Comparator.comparing((int[] itv) -> itv[0]));
 
    PriorityQueue<Integer> heap = new PriorityQueue<>();
    int count = 0;
    for (int[] itv : intervals) {
        if (heap.isEmpty()) {
            count++;
            heap.offer(itv[1]);
        } else {
            if (itv[0] >= heap.peek()) {
                heap.poll();
            } else {
                count++;
            }
 
            heap.offer(itv[1]);
        }
    }
 
    return count;
}

There was a discussion in the comments about why a regular queue is not good enough. I draw an example below to show why sorting based on start time and using a priority queue is necessary.

Category >> Algorithms  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • DS+Algo

    A simple solution would be to use two arrays: start times and end times. Sort them independently. Now keep two pointers to iterate over them. If start time comes first, that means one meeting has started so we need new room, while if end time comes first, that means one meeting is ended so we need lesser room now. The maximum of number of rooms needed at any time would be the answer (kind of similar to Kadane’s algorithm).


    public int minMeetingRooms(List intervals) {
    // Write your code here
    int n = intervals.size();
    List starts = new ArrayList();
    List ends = new ArrayList();
    for(Interval x : intervals) {
    starts.add(x.start);
    ends.add(x.end);
    }
    Collections.sort(starts);
    Collections.sort(ends);
    int i = 0, j = 0, current = 0, result = 0;
    while(i < n) { // since last of ends would be greater than last of starts
    // hence i will reach to end before ends, so no need to check j < n
    if(starts.get(i) result ? current : result; // Update result
    i++;
    } else {
    current--; // One meeting room is emptied, so need lesser meeting rooms now
    // No need to update result here because we only want to maximize result
    j++;
    }
    }
    return result;
    }

  • Michael James Battaglia

    My solution in C# using a BST (it has a time complexity of O(N log N) with a space complexity of O(N)):


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace Whiteboard
    {
    class MeetingRooms
    {
    private class Node
    {
    public int time;
    public int offset;
    public Node left;
    public Node right;

    public Node(int time, int offset)
    {
    this.time = time;
    this.offset = offset;
    this.left = null;
    this.right = null;
    }
    }

    public static void Run()
    {
    int[][] meetings = new int[][] { new int[] { 1100, 1200 }, new int[] { 1130, 1230 }, new int[] { 1200, 1230 } };
    Console.WriteLine(GetMaxMeetingRooms(meetings));
    }

    private static int GetMaxMeetingRooms(int[][] meetings)
    {
    Node root;
    int max = 0;

    root = BuildBST(meetings);
    max = GetMaxRooms(root);

    return max;
    }

    private static Node BuildBST(int[][] meetings)
    {
    Node root = null;

    foreach (int[] times in meetings)
    {
    int start = times[0];
    int end = times[1];

    AddTimeToTree(ref root, start, 1);
    AddTimeToTree(ref root, end, -1);
    }

    return root;
    }

    private static void AddTimeToTree(ref Node node, int time, int offset)
    {
    if (node == null)
    {
    node = new Node(time, offset);
    return;
    }

    if (time < node.time)
    {
    AddTimeToTree(ref node.left, time, offset);
    }
    else
    {
    AddTimeToTree(ref node.right, time, offset);
    }
    }

    private static int GetMaxRooms(Node root)
    {
    int count = 0;
    int max = 0;

    _GetMaxRooms(root, ref count, ref max);

    return max;
    }

    private static void _GetMaxRooms(Node node, ref int count, ref int max)
    {
    if (node == null)
    {
    return;
    }

    _GetMaxRooms(node.left, ref count, ref max);
    count = count + node.offset;
    max = Math.Max(count, max);
    _GetMaxRooms(node.right, ref count, ref max);
    }

    }
    }

  • Srinath Shetty

    Not working for below case
    [[6,15],[13,20],[6,17]]
    Expected: 3
    OP: 1

  • Nitin Sridhar

    //Program is similar to this but start and end meeting time are in different arrays
    // Program to find minimum number of rooms

    import java.util.*;

    class MeetingRoom {

    // Returns minimum number of rooms required
    static int findMeetingRooms(int arr[], int dep[], int n)
    {
    // Sort start and departure arrays
    Arrays.sort(arr);
    Arrays.sort(dep);

    // room_needed indicates number of rooms
    // needed at a time
    int room_needed = 1, result = 1;
    int i = 1, j = 0;

    // Similar to merge in merge sort to process
    // all events in sorted order
    while (i < n && j < n)
    {
    // If next event in sorted order is start time,
    // increment count of rooms needed
    if (arr[i] result)
    result = room_needed;
    }

    // Else decrement count of rooms needed
    else
    {
    room_needed–;
    j++;
    }
    }

    return result;
    }

    // Driver program to test methods of graph class
    public static void main(String[] args)
    {
    int arr[] = {900, 940, 950, 1100, 1500, 1800};
    int dep[] = {910, 1200, 1120, 1130, 1900, 2000};
    int n = arr.length;
    System.out.println(“Minimum Number of Rooms Required = ”
    + findMeetingRooms(arr, dep, n));
    }
    }

  • Sudeep S-r

    Why can’t we follow meeting room one soln ? like if there is an overlap then inc count then no extra space is required

  • Dinh Nhat

    Hey, thanks for a detailed solution.
    Can you also explain how did you come up with this solution? thanks.

  • Cat Racket

    A JavaScript Solution:
    Chinese: https://youtu.be/uEGNNeiMxuI
    English: https://youtu.be/24li7yc91us
    Youtube Channel: youtube.com/c/CatRacketCode
    Facebook: https://www.facebook.com/groups/2094071194216385/

  • Pooja Gupta

    what about 0-2,0-4,0-5,7-8
    It is showing extra count
    answer should be 3 instead it is 4

  • Prashant Nigam

    What would be the runtime (big O) of your approach?

  • Prashant Nigam

    You don’t require a counter, heap size at the end is the required number of rooms

  • It is fine. Output is one meeting room.

  • santosh sunny

    Hi , i got a doubt. Whenever we are taking a new interval, instead of comparing with the smallest ending times why can’t we start comparing from largest of the finished ending times until we get a ending time which is smaller than current interval start time .
    Example : priority Queue : {13,16}
    Current interval : [17,21]
    If we choose 16 -> priority queue :{16,17}
    So here instead of 13 if we choose 16 -> priority queue : {13,17}
    Isn’t the second case better than first one as it will give less collisions compared to first one.

  • Bonsai

    I don’t think your solution is right. Try this example [[7,10],[2,4]]

  • Satish


    public static int meetingRooms(Interval[] intervals) {
    if (intervals.length == 0) {
    return 0;
    }
    // Sort start of interval in ascending order
    Arrays.sort(intervals, new Comparator() {
    public int compare(Interval o1, Interval o2) {
    return o1.start - o2.start;
    }
    });
    int result = intervals.length; // Worst case all room will need its own room
    for (int i = 0; i = intervals[i + 1].start // curr overlap with next
    || (intervals[i].start >= intervals[i + 1].start && intervals[i].end <= intervals[i + 1].end) // curr completely overlap with next
    ) {
    result--;
    }
    }
    return result;
    }

  • Amit

    why wont it?
    It will work.

    First 10-16 is compared with 11-13… count is incremented
    then 11-13 is added to priority queue..
    then 11-13 is compared with 14-17… count is NOT incremented.

    Result: 2

  • rohit

    this will not work for 10-16,11-13,14-17

  • Ankit Shah
  • Ankur

    Instead of Priority Queue take simple queue to store elements but just sort by endTime .


    private static int minMeetingRoomsQueue(Interval[] inte) {
    int c = 0;
    Arrays.sort(inte,new Comparator(){

    @Override
    public int compare(Interval o1, Interval o2) {
    return o1.eTime - o2.eTime;
    }

    });
    Queue q = new LinkedList();
    q.add(inte[0].eTime);
    c++;
    for(int i=1;i<inte.length;i++){
    if(inte[i].sTime < q.peek()){
    c++;
    }else{
    q.poll();
    }
    q.add(inte[i].eTime);
    }
    return c;
    }