Open In App

CSES Solutions - Room Allocation

Last Updated : 24 Feb, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

There is a large hotel, and N customers will arrive soon. Each customer wants to have a single room. You know each customer's arrival and departure day as timings[][] such that timings[i][0] is the arrival time and timings[i][1] is the departure time of ith person. Two customers can stay in the same room if the departure day of the first customer is earlier than the arrival day of the second customer.

What is the minimum number of rooms that are needed to accommodate all customers? And how can the rooms be allocated?

Note: If k is the minimum number of rooms, then the rooms are numbered from 1 to k. Return any valid solution.

Examples:

Input: N = 3, timings[][] = {{1, 2}, {2, 4}, {4, 4}}
Output:
2
1 2 1
Explanation:

  • The first person arrives at time = 1 and gets room 1.
  • The second person arrives at time = 2. Since room 1 is already occupied by the first person, second person will get room 2.
  • The third person arrives at time = 4. Since the first person has already left, third person will get room 1.

Input: N = 4, timings[][] = {{6, 6}, {5, 5}, {6, 6}, {5, 10}}
Output:
3
1 1 3 2
Explanation:

  • The second person arrivesat time = 5 and gets room 1.
  • The fourth person arrives at time = 5. Since room 1 is already occupied by second person, fourth person will get room 2.
  • The first person arrives at time = 6. Since the second person has already left, the first person will get room 1.
  • The third person arrives at time = 6. Since room1 is already occupied by first person and room2 is already occupied by fourth person, the third person will get room 3.

Approach: To solve the problem, follow the below idea:

The problem can be solved using Greedy Approach. Sort all the customers in increasing order of their arrival times. This way, a customer who arrives earlier gets a room before a customer who arrives later. Also, keep track of the departure times of the customers we have already given rooms to, using a Priority Queue (Min Heap).

For each new customer, we check if any of the current customers will leave before the new customer arrives by comparing the arrival time with the top of the priority queue.

  • If any of the current customers will leave, then the new customer can take the room of the customer who is leaving. So, we update the departure time in our system with the departure time of the new customer.
  • If no customer leaves, that means all the rooms are currently occupied and will still be occupied when the new customer arrives. So, we need to provide a new room for this customer and add their departure time to our system.

The minimum number of rooms needed is the largest number of rooms we find ourselves using at any point in this process.

C++
// C++ program to implement 
// room allocation problem.
#include <bits/stdc++.h>
using namespace std;

// function to find the minimum number of rooms and the
// rooms allocated to each customer
void minimumRooms(vector<vector<int> >& timings) {
    
    int n = timings.size();
    
    // vector to store the {arrival, departure, index} of
    // all customers
    vector<vector<int> > vec(n, vector<int>(3));
    for (int i = 0; i < n; i++) {
        vec[i][0] = timings[i][0];
        vec[i][1] = timings[i][1];
        vec[i][2] = i;
    }

    // Sort the vector according to the arrival time of
    // customers
    sort(vec.begin(), vec.end());

    // Min heap to store {departure, room number} to fetch
    // the room which gets vacant the earliest
    priority_queue<pair<int, int>, vector<pair<int, int> >,
                greater<pair<int, int> > >
        occupiedRooms;

    // Variable to store the total number of rooms needed
    int roomCnt = 0;

    // vector to store the room alloted to each customer
    vector<int> ans(n);

    for (int i = 0; i < n; i++) {
        int arrivalTime = vec[i][0];
        int departureTime = vec[i][1];
        int idx = vec[i][2];

        // Check if there are no rooms available or all the
        // rooms are occupied
        if (occupiedRooms.empty()
            || occupiedRooms.top().first >= arrivalTime) {
                
            // If there are no rooms or all the rooms are
            // occupied, then increment the total number of
            // rooms needed and allocate the room to the
            // current customer
            roomCnt += 1;
            occupiedRooms.push({ departureTime, roomCnt });
            ans[idx] = roomCnt;
        }
        else {
            
            // If there is a vacant room, then assign that
            // vacant room to the current customer
            int vacantRoom = occupiedRooms.top().second;
            occupiedRooms.pop();
            occupiedRooms.push(
                { departureTime, vacantRoom });
            ans[idx] = vacantRoom;
        }
    }

    // Print the total rooms needed along with the room
    // allocated to each customer
    cout << roomCnt << "\n";
    for (int i = 0; i < ans.size(); i++)
        cout << ans[i] << " ";
    cout << endl;
}

int main() {

    vector<vector<int>> timings = {{1, 2}, {2, 4}, {4, 4}};
    minimumRooms(timings);
    return 0;
}
Java
// Java program to implement 
// room allocation problem.

import java.util.*;

class GfG {

    // function to find the minimum number of rooms and the
    // rooms allocated to each customer
    static void minimumRooms(int[][] timings) {
        
        int n = timings.length;
        
        // array to store the {arrival, departure, index} of
        // all customers
        int[][] vec = new int[n][3];
        for (int i = 0; i < n; i++) {
            vec[i][0] = timings[i][0];
            vec[i][1] = timings[i][1];
            vec[i][2] = i;
        }

        // Sort the array according to the arrival time of
        // customers
        Arrays.sort(vec, Comparator.comparingInt(a -> a[0]));

        // Min heap to store {departure, room number} to fetch
        // the room which gets vacant the earliest
        PriorityQueue<int[]> occupiedRooms = 
        new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));

        // Variable to store the total number of rooms needed
        int roomCnt = 0;

        // array to store the room allotted to each customer
        int[] ans = new int[n];

        for (int i = 0; i < n; i++) {
            int arrivalTime = vec[i][0];
            int departureTime = vec[i][1];
            int idx = vec[i][2];

            // Check if there are no rooms available or all the
            // rooms are occupied
            if (occupiedRooms.isEmpty() || 
            occupiedRooms.peek()[0] >= arrivalTime) {
                    
                // If there are no rooms or all the rooms are
                // occupied, then increment the total number of
                // rooms needed and allocate the room to the
                // current customer
                roomCnt += 1;
                occupiedRooms.add(new int[]{departureTime, roomCnt});
                ans[idx] = roomCnt;
            } else {
                
                // If there is a vacant room, then assign that
                // vacant room to the current customer
                int vacantRoom = occupiedRooms.poll()[1];
                occupiedRooms.add(new int[]{departureTime, vacantRoom});
                ans[idx] = vacantRoom;
            }
        }

        // Print the total rooms needed along with the room
        // allocated to each customer
        System.out.println(roomCnt);
        for (int i = 0; i < ans.length; i++)
            System.out.print(ans[i] + " ");
        System.out.println();
    }

    public static void main(String[] args) {
        int[][] timings = {{1, 2}, {2, 4}, {4, 4}};
        minimumRooms(timings);
    }
}
Python
# Python program to implement 
# room allocation problem.
import heapq

# function to find the minimum number of rooms and the
# rooms allocated to each customer
def minimumRooms(timings):
    
    n = len(timings)
    
    # list to store the {arrival, departure, index} of
    # all customers
    vec = [[timings[i][0], timings[i][1], i] for i in range(n)]

    # Sort the list according to the arrival time of
    # customers
    vec.sort()

    # Min heap to store {departure, room number} to fetch
    # the room which gets vacant the earliest
    occupiedRooms = []

    # Variable to store the total number of rooms needed
    roomCnt = 0

    # list to store the room allotted to each customer
    ans = [0] * n

    for i in range(n):
        arrivalTime, departureTime, idx = vec[i]

        # Check if there are no rooms available or all the
        # rooms are occupied
        if not occupiedRooms or occupiedRooms[0][0] >= arrivalTime:
                
            # If there are no rooms or all the rooms are
            # occupied, then increment the total number of
            # rooms needed and allocate the room to the
            # current customer
            roomCnt += 1
            heapq.heappush(occupiedRooms, (departureTime, roomCnt))
            ans[idx] = roomCnt
        else:
            
            # If there is a vacant room, then assign that
            # vacant room to the current customer
            vacantRoom = heapq.heappop(occupiedRooms)[1]
            heapq.heappush(occupiedRooms, (departureTime, vacantRoom))
            ans[idx] = vacantRoom

    # Print the total rooms needed along with the room
    # allocated to each customer
    print(roomCnt)
    print(*ans)

if __name__ == "__main__":
    timings = [[1, 2], [2, 4], [4, 4]]
    minimumRooms(timings)
C#
// C# program to implement 
// room allocation problem.

using System;
using System.Collections.Generic;

class Pair {
    public int first, second;
    public Pair(int first, int second) {
        this.first = first;
        this.second = second;
    }
}

class intComparer : IComparer<Pair> {
    public int Compare(Pair a, Pair b) {
        if (a.first > b.first)
            return 1;
        else if (a.first < b.first)
            return -1;
        return 0;
    }
}

class GfG {
    
    // function to find the minimum number of rooms and the
    // rooms allocated to each customer
    static void minimumRooms(int[][] timings) {
        
        int n = timings.Length;
        
        // array to store the {arrival, departure, index} of
        // all customers
        int[][] vec = new int[n][];
        for (int i = 0; i < n; i++) {
            vec[i] = new int[] { timings[i][0], timings[i][1], i };
        }

        // Sort the array according to the arrival time of
        // customers
        Array.Sort(vec, (a, b) => a[0].CompareTo(b[0]));

        // Min heap to store {departure, room number} to fetch
        // the room which gets vacant the earliest
        PriorityQueue<Pair> occupiedRooms = new PriorityQueue<Pair>(new intComparer());

        // Variable to store the total number of rooms needed
        int roomCnt = 0;

        // array to store the room allotted to each customer
        int[] ans = new int[n];

        for (int i = 0; i < n; i++) {
            int arrivalTime = vec[i][0];
            int departureTime = vec[i][1];
            int idx = vec[i][2];

            // Check if there are no rooms available or all the
            // rooms are occupied
            if (occupiedRooms.Count == 0 || occupiedRooms.Peek().first >= arrivalTime) {
                    
                // If there are no rooms or all the rooms are
                // occupied, then increment the total number of
                // rooms needed and allocate the room to the
                // current customer
                roomCnt += 1;
                occupiedRooms.Enqueue(new Pair(departureTime, roomCnt));
                ans[idx] = roomCnt;
            } else {
                
                // If there is a vacant room, then assign that
                // vacant room to the current customer
                int vacantRoom = occupiedRooms.Dequeue().second;
                occupiedRooms.Enqueue(new Pair(departureTime, vacantRoom));
                ans[idx] = vacantRoom;
            }
        }

        // Print the total rooms needed along with the room
        // allocated to each customer
        Console.WriteLine(roomCnt);
        Console.WriteLine(string.Join(" ", ans));
    }

    static void Main() {
        int[][] timings = { new int[] { 1, 2 }, 
        new int[] { 2, 4 }, new int[] { 4, 4 } };
        minimumRooms(timings);
    }
}

class PriorityQueue<T> {
    private List<T> heap;
    private IComparer<T> comparer;

    public PriorityQueue(IComparer<T> comparer = null) {
        this.heap = new List<T>();
        this.comparer = comparer ?? Comparer<T>.Default;
    }

    public int Count => heap.Count;

    // Enqueue operation
    public void Enqueue(T item) {
        heap.Add(item);
        int i = heap.Count - 1;
        while (i > 0) {
            int parent = (i - 1) / 2;
            if (comparer.Compare(heap[parent], heap[i]) <= 0)
                break;
            Swap(parent, i);
            i = parent;
        }
    }
    
    public T Peek() {
        return heap[0];
    }

    // Dequeue operation
    public T Dequeue() {
        if (heap.Count == 0)
            throw new InvalidOperationException("Priority queue is empty.");
        T result = heap[0];
        int last = heap.Count - 1;
        heap[0] = heap[last];
        heap.RemoveAt(last);
        last--;
        int i = 0;
        while (true) {
            int left = 2 * i + 1;
            if (left > last)
                break;
            int right = left + 1;
            int minChild = left;
            if (right <= last && comparer.Compare(heap[right], heap[left]) < 0)
                minChild = right;
            if (comparer.Compare(heap[i], heap[minChild]) <= 0)
                break;
            Swap(i, minChild);
            i = minChild;
        }
        return result;
    }

    // Swap two elements in the heap
    private void Swap(int i, int j) {
        T temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }
}
JavaScript
// Function to find the minimum number of rooms and the
// rooms allocated to each customer
function solve(timings) {
    
    // Sort the timings array based on arrival times
    timings.sort((a, b) => a[0] - b[0]);

    // Min heap to store {departure, room number} to fetch
    // the room which gets vacant the earliest
    let occupiedRooms = new MinHeap();

    // Variable to store the total number of rooms needed
    let roomCnt = 0;

    // Array to store the room allocated to each customer
    let ans = [];

    for (let i = 0; i < timings.length; i++) {
        let arrivalTime = timings[i][0];
        let departureTime = timings[i][1];

        // Check if there are no rooms available or all the
        // rooms are occupied
        if (occupiedRooms.isEmpty() || occupiedRooms.top().departure >= arrivalTime) {
            // If there are no rooms or all the rooms are
            // occupied, then increment the total number of
            // rooms needed and allocate the room to the
            // current customer
            roomCnt++;
            occupiedRooms.push({ departure: departureTime, room: roomCnt });
            ans.push(roomCnt);
        } else {
            // If there is a vacant room, then assign that
            // vacant room to the current customer
            let vacantRoom = occupiedRooms.pop().room;
            occupiedRooms.push({ departure: departureTime, room: vacantRoom });
            ans.push(vacantRoom);
        }
    }

    // Print the total rooms needed along with the room
    // allocated to each customer
    console.log(roomCnt);
    console.log(ans.join(" "));
}

// Priority queue implementation for the min heap
class MinHeap {
    constructor() {
        this.heap = [];
    }

    push(value) {
        this.heap.push(value);
        this.heapifyUp();
    }

    pop() {
        if (this.isEmpty()) return null;
        this.swap(0, this.heap.length - 1);
        const poppedValue = this.heap.pop();
        this.heapifyDown();
        return poppedValue;
    }

    top() {
        return this.heap[0];
    }

    isEmpty() {
        return this.heap.length === 0;
    }

    heapifyUp() {
        let currentIdx = this.heap.length - 1;
        let parentIdx = Math.floor((currentIdx - 1) / 2);
        while (currentIdx > 0 && this.heap[currentIdx].departure < this.heap[parentIdx].departure) {
            this.swap(currentIdx, parentIdx);
            currentIdx = parentIdx;
            parentIdx = Math.floor((currentIdx - 1) / 2);
        }
    }

    heapifyDown() {
        let currentIdx = 0;
        let leftChildIdx = 2 * currentIdx + 1;
        while (leftChildIdx < this.heap.length) {
            let rightChildIdx = 2 * currentIdx + 2 < this.heap.length ? 2 * currentIdx + 2 : -1;
            let idxToSwap;
            if (rightChildIdx !== -1 && this.heap[rightChildIdx].departure < this.heap[leftChildIdx].departure) {
                idxToSwap = rightChildIdx;
            } else {
                idxToSwap = leftChildIdx;
            }
            if (this.heap[idxToSwap].departure < this.heap[currentIdx].departure) {
                this.swap(currentIdx, idxToSwap);
                currentIdx = idxToSwap;
                leftChildIdx = 2 * currentIdx + 1;
            } else {
                break;
            }
        }
    }

    swap(i, j) {
        [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
    }
}

let timings = [
    [1, 2],
    [2, 4],
    [4, 4]
];

solve(timings);

Output
2
1 2 1 

Time Complexity: O(n * log n), where n is the number of customers.
Auxiliary Space: O(n)



Next Article
Practice Tags :

Similar Reads