import heapq
class Solution:
def smallestChair(self, times, targetFriend):
n = len(times)
arrivals = []
for i, (arr, leave) in enumerate(times):
arrivals.append((arr, i, leave))
arrivals.sort() # Sort by arrival time
occupied = [] # Min-heap of (leave_time, chair_number)
free_chairs = [] # Min-heap of available chair numbers
next_chair = 0 # Next new chair to use
for arr_time, friend, leave_time in arrivals:
# Free up chairs for friends who have already left
while occupied and occupied[0][0] <= arr_time:
left_time, chair_num = heapq.heappop(occupied)
heapq.heappush(free_chairs, chair_num)
# Assign the smallest available chair
if free_chairs:
chair = heapq.heappop(free_chairs)
else:
chair = next_chair
next_chair += 1
heapq.heappush(occupied, (leave_time, chair))
if friend == targetFriend:
return chair
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
class Solution {
public:
int smallestChair(vector<vector<int>>& times, int targetFriend) {
int n = times.size();
vector<tuple<int, int, int>> arrivals;
for (int i = 0; i < n; ++i) {
arrivals.emplace_back(times[i][0], i, times[i][1]);
}
sort(arrivals.begin(), arrivals.end());
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> occupied;
priority_queue<int, vector<int>, greater<int>> freeChairs;
int nextChair = 0;
for (auto& [arr, friendIdx, leave] : arrivals) {
while (!occupied.empty() && occupied.top().first <= arr) {
freeChairs.push(occupied.top().second);
occupied.pop();
}
int chair;
if (!freeChairs.empty()) {
chair = freeChairs.top();
freeChairs.pop();
} else {
chair = nextChair++;
}
occupied.push({leave, chair});
if (friendIdx == targetFriend)
return chair;
}
return -1;
}
};
import java.util.*;
class Solution {
public int smallestChair(int[][] times, int targetFriend) {
int n = times.length;
List<int[]> arrivals = new ArrayList<>();
for (int i = 0; i < n; i++) {
arrivals.add(new int[]{times[i][0], i, times[i][1]});
}
arrivals.sort(Comparator.comparingInt(a -> a[0]));
PriorityQueue<int[]> occupied = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
PriorityQueue<Integer> freeChairs = new PriorityQueue<>();
int nextChair = 0;
for (int[] arr : arrivals) {
int arrTime = arr[0], friendIdx = arr[1], leaveTime = arr[2];
while (!occupied.isEmpty() && occupied.peek()[0] <= arrTime) {
freeChairs.offer(occupied.poll()[1]);
}
int chair;
if (!freeChairs.isEmpty()) {
chair = freeChairs.poll();
} else {
chair = nextChair++;
}
occupied.offer(new int[]{leaveTime, chair});
if (friendIdx == targetFriend)
return chair;
}
return -1;
}
}
class MinHeap {
constructor(compare) {
this.data = [];
this.compare = compare;
}
push(item) {
this.data.push(item);
this._siftUp();
}
pop() {
if (this.data.length === 1) return this.data.pop();
const top = this.data[0];
this.data[0] = this.data.pop();
this._siftDown();
return top;
}
peek() {
return this.data[0];
}
size() {
return this.data.length;
}
_siftUp() {
let i = this.data.length - 1;
while (i > 0) {
let p = Math.floor((i - 1) / 2);
if (this.compare(this.data[i], this.data[p]) < 0) {
[this.data[i], this.data[p]] = [this.data[p], this.data[i]];
i = p;
} else break;
}
}
_siftDown() {
let i = 0;
const n = this.data.length;
while (true) {
let l = 2 * i + 1, r = 2 * i + 2, smallest = i;
if (l < n && this.compare(this.data[l], this.data[smallest]) < 0) smallest = l;
if (r < n && this.compare(this.data[r], this.data[smallest]) < 0) smallest = r;
if (smallest === i) break;
[this.data[i], this.data[smallest]] = [this.data[smallest], this.data[i]];
i = smallest;
}
}
}
var smallestChair = function(times, targetFriend) {
let arrivals = times.map((time, i) => [time[0], i, time[1]]);
arrivals.sort((a, b) => a[0] - b[0]);
let occupied = new MinHeap((a, b) => a[0] - b[0]);
let freeChairs = new MinHeap((a, b) => a - b);
let nextChair = 0;
for (let [arrTime, friend, leaveTime] of arrivals) {
while (occupied.size() > 0 && occupied.peek()[0] <= arrTime) {
freeChairs.push(occupied.pop()[1]);
}
let chair;
if (freeChairs.size() > 0) {
chair = freeChairs.pop();
} else {
chair = nextChair++;
}
occupied.push([leaveTime, chair]);
if (friend === targetFriend) return chair;
}
return -1;
};
You are given an array times
where times[i] = [arrive_i, leave_i]
describes the arrival and leaving times of the i
-th friend at a party. Each friend takes a seat when they arrive and leaves it when they go. There are infinite chairs, numbered from 0
upwards.
When a friend arrives, they always take the smallest-numbered unoccupied chair. If multiple friends arrive at the same time, they are assigned seats in order of increasing i
(their index in times
).
You are also given an integer targetFriend
. Your task is to return the number of the chair that the targetFriend
will sit in.
At first glance, the problem seems approachable by simulating the process: for every friend's arrival, scan the list of chairs to find the smallest one not currently occupied. However, with many friends and overlapping intervals, this naïve approach could become slow and inefficient.
To optimize, we need a way to efficiently track which chairs are available at any given time and always be able to quickly select the smallest available chair. We also need to handle friends leaving and freeing up their chairs.
The key is to process events (arrivals and departures) in chronological order, so we always know the current state of chair occupancy. Using data structures like heaps (priority queues) can help us efficiently manage available chairs and the timing of departures.
targetFriend
, return the chair assigned to them.This approach ensures that both assigning and releasing chairs are handled efficiently, and we always meet the problem's requirement of giving each friend the smallest available chair at their arrival time.
Let's consider times = [[1,4],[2,3],[4,6]]
and targetFriend = 1
.
Since targetFriend = 1
, and they were assigned chair 1 at their arrival, the answer is 1.
Overall, the optimized solution is efficient and suitable for large inputs.
The key insight is to process arrivals and departures in chronological order, using heaps to efficiently track available and occupied chairs. This ensures that each friend gets the smallest possible chair number at their arrival, and that released chairs are quickly reused. The approach is both efficient and elegant, leveraging priority queues to maintain the problem's constraints with minimal overhead.