Back to all solutions

#1847 - Closest Room

Problem Description

There is a hotel with n rooms. The rooms are represented by a 2D integer array rooms where rooms[i] = [roomIdi, sizei] denotes that there is a room with room number roomIdi and size equal to sizei. Each roomIdi is guaranteed to be unique.

You are also given k queries in a 2D array queries where queries[j] = [preferredj, minSizej].

The answer to the jth query is the room number id of a room such that:

  • The room has a size of at least minSizej, and
  • abs(id - preferredj) is minimized, where abs(x) is the absolute value of x.

If there is a tie in the absolute difference, then use the room with the smallest such id.

If there is no such room, the answer is -1.

Return an array answer of length k where answer[j] contains the answer to the jth query.

Solution

/**
 * @param {number[][]} rooms
 * @param {number[][]} queries
 * @return {number[]}
 */
var closestRoom = function(rooms, queries) {
  rooms.sort((a, b) => b[1] - a[1]);
  const sortedQueries = queries
    .map((q, i) => [q[0], q[1], i])
    .sort((a, b) => b[1] - a[1]);

  const result = new Array(queries.length).fill(-1);
  const roomIds = [];
  let roomIndex = 0;

  for (const [preferred, minSize, queryIndex] of sortedQueries) {
    while (roomIndex < rooms.length && rooms[roomIndex][1] >= minSize) {
      insertSorted(rooms[roomIndex][0]);
      roomIndex++;
    }

    result[queryIndex] = findClosestId(preferred);
  }

  return result;

  function insertSorted(id) {
    let left = 0;
    let right = roomIds.length;
    while (left < right) {
      const mid = Math.floor((left + right) / 2);
      if (roomIds[mid] < id) left = mid + 1;
      else right = mid;
    }
    roomIds.splice(left, 0, id);
  }

  function findClosestId(target) {
    if (!roomIds.length) return -1;

    let left = 0;
    let right = roomIds.length - 1;
    let closest = roomIds[0];
    let minDiff = Math.abs(closest - target);

    while (left <= right) {
      const mid = Math.floor((left + right) / 2);
      const id = roomIds[mid];
      const diff = Math.abs(id - target);

      if (diff < minDiff || (diff === minDiff && id < closest)) {
        minDiff = diff;
        closest = id;
      }

      if (id < target) left = mid + 1;
      else if (id > target) right = mid - 1;
      else break;
    }

    return closest;
  }
};