最小未被占据椅子的编号
难度:
标签:
题目描述
代码结果
运行时间: 129 ms, 内存: 20.4 MB
/* Problem statement:
There are n friends attending a party, each arriving and leaving at specific times. Each friend will occupy the smallest numbered unoccupied chair upon arrival. We need to determine the chair number occupied by the target friend.
Solution using Java Stream API:
1. Sort the friends by their arrival times using Stream.
2. Use a TreeSet to keep track of the available chairs.
3. Iterate over sorted events and manage chair allocation and deallocation.
*/
import java.util.*;
import java.util.stream.*;
public class PartyChairsStream {
public int smallestChair(int[][] times, int targetFriend) {
int n = times.length;
// List of events (arrival or leaving)
List<int[]> events = IntStream.range(0, n)
.mapToObj(i -> new int[][]{{times[i][0], i, 1}, {times[i][1], i, -1}})
.flatMap(Arrays::stream)
.sorted((a, b) -> a[0] == b[0] ? a[2] - b[2] : a[0] - b[0])
.collect(Collectors.toList());
// TreeSet to manage available chairs
TreeSet<Integer> availableChairs = IntStream.range(0, n).boxed().collect(Collectors.toCollection(TreeSet::new));
Map<Integer, Integer> occupiedChairs = new HashMap<>();
for (int[] event : events) {
int time = event[0];
int friend = event[1];
int type = event[2];
if (type == 1) { // arrival
int chair = availableChairs.pollFirst();
occupiedChairs.put(friend, chair);
if (friend == targetFriend) {
return chair;
}
} else { // leaving
int chair = occupiedChairs.remove(friend);
availableChairs.add(chair);
}
}
return -1; // should never reach here
}
}
解释
方法:
首先,解题思路是将每个朋友的到达和离开时间转换为一个事件列表,并包含每个朋友的索引。对这个列表根据到达时间进行排序。使用一个最小堆来跟踪当前可用的椅子编号,另一个最小堆来维护离开时间和对应的椅子编号。遍历每个事件,如果有朋友离开(即当前时间大于等于堆顶的离开时间),则将对应的椅子编号放回可用椅子堆中。如果有朋友到达,则从可用椅子堆中取出最小的椅子编号,并记录该朋友使用的椅子。如果当前到达的朋友是目标朋友,直接返回其所使用的椅子编号。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
在处理离开事件时,如何确保在多个朋友同时离开时,椅子编号能正确地被回收并且保持最小编号优先的原则?
▷🦆
代码实现中,当目标朋友到达时直接返回其椅子编号。如果在目标朋友到达之前处理完所有事件会对结果有什么影响?
▷