Open In App

CSES Solutions – Room Allocation

Last Updated : 28 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
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?

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 arrives at 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.

Step-by-step algorithm:

  • Store the arrival, departure and index of all the customers in a 2D vector, say vec[][].
  • Sort the 2D vector vec[][] in increasing order of the arrival times.
  • Maintain a min heap of pairs, say occupiedRooms with the first element as the departure time of a person and second element as the room number which the person occupied.
  • Iterate over all the customers in vec[][]. For each customer, check if the room at the top of the min heap becomes vacant before the current customer arrives.
  • If the room at the top becomes vacant, then pop the room from the min heap and insert the departure of the current customer along with the room.
  • Otherwise, if the room at the top does not become vacant, then no room will become vacant. So, we increase the room count and assign the new room to the current customer.
  • Store the room assigned to each customer in a vector, say ans and print it.

Below is the implementation of the algorithm:

C++
#include <bits/stdc++.h>
#define ll long long int

using namespace std;

// function to find the minimum number of rooms and the
// rooms allocated to each customer
void solve(vector<vector<ll> >& timings, ll N)
{
    // vector to store the {arrival, departure, index} of
    // all customers
    vector<vector<ll> > vec(N, vector<ll>(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<ll, ll>, vector<pair<ll, ll> >,
                greater<pair<ll, ll> > >
        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++) {
        ll arrivalTime = vec[i][0];
        ll departureTime = vec[i][1];
        ll 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] << " ";
}

int main()
{
    // Sample Input
    ll N = 3;
    vector<vector<ll> > timings
        = { { 1, 2 }, { 2, 4 }, { 4, 4 } };

    solve(timings, N);
    // your code goes here
    return 0;
}
Java
import java.util.*;

public class Main {
    // Function to find the minimum number of rooms and the rooms allocated to each customer
    static void solve(ArrayList<ArrayList<Long>> timings, int N) {
        // ArrayList to store the {arrival, departure, index} of all customers
        ArrayList<ArrayList<Long>> vec = new ArrayList<>(N);
        for (int i = 0; i < N; i++) {
            vec.add(new ArrayList<>(Arrays.asList(timings.get(i).get(0), timings.get(i).get(1), (long) i)));
        }

        // Sort the ArrayList according to the arrival time of customers
        Collections.sort(vec, Comparator.comparingLong(a -> a.get(0)));

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

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

        // ArrayList to store the room allotted to each customer
        ArrayList<Integer> ans = new ArrayList<>(Collections.nCopies(N, 0));

        for (int i = 0; i < N; i++) {
            long arrivalTime = vec.get(i).get(0);
            long departureTime = vec.get(i).get(1);
            long idx = vec.get(i).get(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 long[] { departureTime, roomCnt });
                ans.set((int) idx, roomCnt);
            } else {
                // If there is a vacant room, then assign that vacant room to the current customer
                long[] vacantRoom = occupiedRooms.poll();
                vacantRoom[0] = departureTime;
                occupiedRooms.add(vacantRoom);
                ans.set((int) idx, (int) vacantRoom[1]);
            }
        }

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

    public static void main(String[] args) {
        // Sample Input
        int N = 3;
        ArrayList<ArrayList<Long>> timings = new ArrayList<>(Arrays.asList(
                new ArrayList<>(Arrays.asList(1L, 2L)),
                new ArrayList<>(Arrays.asList(2L, 4L)),
                new ArrayList<>(Arrays.asList(4L, 4L))
        ));

        solve(timings, N);
    }
}
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]];
    }
}

// Sample Input
let timings = [
    [1, 2],
    [2, 4],
    [4, 4]
];

// Call the solve function with the timings array
solve(timings);
Python3
import heapq

# Function to find the minimum number of rooms and the rooms allocated to each customer
def solve(timings):
    # Vector to store the {arrival, departure, index} of all customers
    vec = [(arrival, departure, idx) for idx, (arrival, departure) in enumerate(timings)]

    # Sort the vector 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] * len(timings)

    for arrival, departure, idx in vec:
        # Check if there are no rooms available or all the rooms are occupied
        if not occupiedRooms or occupiedRooms[0][0] >= arrival:
            # 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, (departure, roomCnt))
            ans[idx] = roomCnt
        else:
            # If there is a vacant room, then assign that vacant room to the current customer
            departureTime, vacantRoom = heapq.heappop(occupiedRooms)
            heapq.heappush(occupiedRooms, (departure, vacantRoom))
            ans[idx] = vacantRoom

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

# Sample Input
timings = [[1, 2], [2, 4], [4, 4]]

solve(timings)

Output
2
1 2 1 



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



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads