1847. 最近的房间
一个酒店里有 n
个房间,这些房间用二维整数数组 rooms
表示,其中 rooms[i] = [roomIdi, sizei]
表示有一个房间号为 roomIdi
的房间且它的面积为 sizei
。每一个房间号 roomIdi
保证是 独一无二 的。
同时给你 k
个查询,用二维数组 queries
表示,其中 queries[j] = [preferredj, minSizej]
。第 j
个查询的答案是满足如下条件的房间 id
:
minSizej
,且abs(id - preferredj)
的值 最小 ,其中 abs(x)
是 x
的绝对值。如果差的绝对值有 相等 的,选择 最小 的 id
。如果 没有满足条件的房间 ,答案为 -1
。
请你返回长度为 k
的数组 answer
,其中 answer[j]
为第 j
个查询的结果。
示例 1:
输入:rooms = [[2,2],[1,2],[3,2]], queries = [[3,1],[3,3],[5,2]] 输出:[3,-1,3] 解释:查询的答案如下: 查询 [3,1] :房间 3 的面积为 2 ,大于等于 1 ,且号码是最接近 3 的,为 abs(3 - 3) = 0 ,所以答案为 3 。 查询 [3,3] :没有房间的面积至少为 3 ,所以答案为 -1 。 查询 [5,2] :房间 3 的面积为 2 ,大于等于 2 ,且号码是最接近 5 的,为 abs(3 - 5) = 2 ,所以答案为 3 。
示例 2:
输入:rooms = [[1,4],[2,3],[3,5],[4,1],[5,2]], queries = [[2,3],[2,4],[2,5]] 输出:[2,1,3] 解释:查询的答案如下: 查询 [2,3] :房间 2 的面积为 3 ,大于等于 3 ,且号码是最接近的,为 abs(2 - 2) = 0 ,所以答案为 2 。 查询 [2,4] :房间 1 和 3 的面积都至少为 4 ,答案为 1 因为它房间编号更小。 查询 [2,5] :房间 3 是唯一面积大于等于 5 的,所以答案为 3 。
提示:
n == rooms.length
1 <= n <= 105
k == queries.length
1 <= k <= 104
1 <= roomIdi, preferredj <= 107
1 <= sizei, minSizej <= 107
原站题解
rust 解法, 执行用时: 64 ms, 内存消耗: 8.7 MB, 提交时间: 2023-10-08 17:54:07
use std::collections::BTreeSet; impl Solution { pub fn closest_room(mut rooms: Vec<Vec<i32>>, mut queries: Vec<Vec<i32>>) -> Vec<i32> { rooms.sort_unstable_by_key(|x| x[1]); for (pos, query) in queries.iter_mut().enumerate() { query.push(pos as i32); } queries.sort_unstable_by_key(|x| x[1]); let mut set = BTreeSet::new(); let mut res = vec![-1; queries.len()]; while queries.len() > 0 { while rooms.len() > 0 && rooms[rooms.len() - 1][1] >= queries[queries.len() - 1][1] { set.insert(rooms.pop().unwrap()[0]); } let pos = queries.last().unwrap()[2] as usize; let prefer = queries.pop().unwrap()[0]; res[pos] = match (set.range(prefer..).next(), set.range(..prefer).last()) { (Some(&solu1), Some(&solu2)) => if (solu2 - prefer).abs() <= (solu1 - prefer).abs() { solu2 } else { solu1 }, (Some(&solu1), None) => solu1, (None, Some(&solu2)) => solu2, (None, None) => -1 } } res } }
golang 解法, 执行用时: 296 ms, 内存消耗: 23.6 MB, 提交时间: 2023-10-08 17:53:39
import ( "math/rand" ) type node struct { Ch [2]*node priority int Val int } func (o *node) cmp(b int) int { switch { case b < o.Val: return 0 case b > o.Val: return 1 default: return -1 } } func (o *node) rotate(d int) *node { x := o.Ch[d^1] o.Ch[d^1] = x.Ch[d] x.Ch[d] = o return x } type Treap struct { root *node } func (t *Treap) _put(o *node, val int) *node { if o == nil { return &node{priority: rand.Int(), Val: val} } d := o.cmp(val) o.Ch[d] = t._put(o.Ch[d], val) if o.Ch[d].priority > o.priority { o = o.rotate(d ^ 1) } return o } func (t *Treap) Put(val int) { t.root = t._put(t.root, val) } func (t *Treap) _delete(o *node, val int) *node { if d := o.cmp(val); d >= 0 { o.Ch[d] = t._delete(o.Ch[d], val) return o } if o.Ch[1] == nil { return o.Ch[0] } if o.Ch[0] == nil { return o.Ch[1] } d := 0 if o.Ch[0].priority > o.Ch[1].priority { d = 1 } o = o.rotate(d) o.Ch[d] = t._delete(o.Ch[d], val) return o } func (t *Treap) Delete(val int) { t.root = t._delete(t.root, val) } func (t *Treap) LowerBound(val int) (lb *node) { for o := t.root; o != nil; { switch c := o.cmp(val); { case c == 0: lb = o o = o.Ch[0] case c > 0: o = o.Ch[1] default: return o } } return } func (t *Treap) HighBound(val int) (lb *node) { for o := t.root; o != nil; { switch c := o.cmp(val); { case c == 0: o = o.Ch[0] case c > 0: lb = o o = o.Ch[1] default: return o } } return } func closestRoom(rooms [][]int, queries [][]int) []int { ans := make([]int, len(queries)) q := make([][]int, len(queries)) set:= &Treap{} for i := 0; i < len(queries); i++ { q[i] = append(queries[i], i) } sort.Slice(rooms, func(i, j int) bool { return rooms[i][1] > rooms[j][1] }) sort.Slice(q, func(i, j int) bool { return q[i][1] > q[j][1] }) j:=0 for i := 0; i < len(q); i++ { for j< len(rooms) && rooms[j][1] >= q[i][1] { set.Put(rooms[j][0]) j++ } if j ==0{ ans[q[i][2]]=-1 continue } hb := set.LowerBound(q[i][0]) if hb!=nil && hb.Val == q[i][0]{ ans[q[i][2]]=hb.Val continue } lb := set.HighBound(q[i][0]) // fmt.Println(lb,hb) if lb ==nil || (hb!=nil && q[i][0]-lb.Val > hb.Val-q[i][0]){ ans[q[i][2]]=hb.Val }else { ans[q[i][2]]=lb.Val } } return ans }
java 解法, 执行用时: 98 ms, 内存消耗: 84.1 MB, 提交时间: 2023-10-08 17:53:01
class Solution { public int[] closestRoom(int[][] rooms, int[][] queries) { // 按房间大小排序 Arrays.sort(rooms,(a,b)->b[1]-a[1]); List<int[]> list = new ArrayList<>(); int roomCap = rooms.length, querySize = queries.length; for (int i=0;i<querySize;i++){ list.add(new int[]{i,queries[i][0],queries[i][1]}); } // 按最小大小排序 Collections.sort(list,(a,b)->b[2]-a[2]); TreeSet<Integer> roomIds = new TreeSet<>(); int[] res = new int[querySize]; int idx = 0; for (int[] query : list) { int pos = query[0], preferred = query[1], minSize = query[2]; // 维护符合要求的房间id while (idx<roomCap && rooms[idx][1]>=minSize){ roomIds.add(rooms[idx][0]); idx++; } // 获取请求结果 if (roomIds.isEmpty()) res[pos] = -1; else { Integer ceiling = roomIds.ceiling(preferred); Integer floor = roomIds.floor(preferred); if (ceiling==null) res[pos]=floor; else if (floor==null) res[pos]=ceiling; else res[pos] = preferred-floor<=ceiling-preferred ? floor : ceiling; } } return res; } }
python3 解法, 执行用时: 1276 ms, 内存消耗: 64.9 MB, 提交时间: 2023-10-08 17:52:47
class Event: """ op: 事件的类型,0 表示房间,1 表示询问 size: 房间的 size 或者询问的 minSize idx: 房间的 roomId 或者询问的 preferred origin: 房间在数组 room 中的原始编号或者询问在数组 queries 中的原始编号 """ def __init__(self, op: int, size: int, idx: int, origin: int): self.op = op self.size = size self.idx = idx self.origin = origin """ 自定义比较函数,按照事件的 size 降序排序 如果 size 相同,优先考虑房间 """ def __lt__(self, other: "Event") -> bool: return self.size > other.size or (self.size == other.size and self.op < other.op) class Solution: def closestRoom(self, rooms: List[List[int]], queries: List[List[int]]) -> List[int]: import sortedcontainers n = len(queries) events = list() for i, (roomId, size) in enumerate(rooms): # 房间事件 events.append(Event(0, size, roomId, i)) for i, (minSize, preferred) in enumerate(queries): # 询问事件 events.append(Event(1, preferred, minSize, i)) events.sort() ans = [-1] * n # 存储房间 roomId 的有序集合 # 需要导入 sortedcontainers 库 valid = sortedcontainers.SortedList() for event in events: if event.op == 0: # 房间事件,将 roomId 加入有序集合 valid.add(event.idx) else: # 询问事件 dist = float("inf") # 查找最小的大于等于 preferred 的元素 x = valid.bisect_left(event.idx) if x != len(valid) and valid[x] - event.idx < dist: dist = valid[x] - event.idx ans[event.origin] = valid[x] if x != 0: # 查找最大的严格小于 preferred 的元素 x -= 1 if event.idx - valid[x] <= dist: dist = event.idx - valid[x] ans[event.origin] = valid[x] return ans
cpp 解法, 执行用时: 588 ms, 内存消耗: 183.1 MB, 提交时间: 2023-10-08 17:51:34
struct Event { // 事件的类型,0 表示房间,1 表示询问 int type; // 房间的 size 或者询问的 minSize int size; // 房间的 roomId 或者询问的 preferred int id; // 房间在数组 room 中的原始编号或者询问在数组 queries 中的原始编号 int origin; Event(int _type, int _size, int _id, int _origin): type(_type), size(_size), id(_id), origin(_origin) {} // 自定义比较函数,按照事件的 size 降序排序 // 如果 size 相同,优先考虑房间 bool operator< (const Event& that) const { return size > that.size || (size == that.size && type < that.type); } }; class Solution { public: vector<int> closestRoom(vector<vector<int>>& rooms, vector<vector<int>>& queries) { int m = rooms.size(); int n = queries.size(); vector<Event> events; for (int i = 0; i < m; ++i) { // 房间事件 events.emplace_back(0, rooms[i][1], rooms[i][0], i); } for (int i = 0; i < n; ++i) { // 询问事件 events.emplace_back(1, queries[i][1], queries[i][0], i); } sort(events.begin(), events.end()); vector<int> ans(n, -1); // 存储房间 roomId 的有序集合 set<int> valid; for (const auto& event: events) { if (event.type == 0) { // 房间事件,将 roomId 加入有序集合 valid.insert(event.id); } else { // 询问事件 int dist = INT_MAX; // 查找最小的大于等于 preferred 的元素 auto it = valid.lower_bound(event.id); if (it != valid.end() && *it - event.id < dist) { dist = *it - event.id; ans[event.origin] = *it; } if (it != valid.begin()) { // 查找最大的严格小于 preferred 的元素 it = prev(it); if (event.id - *it <= dist) { dist = event.id - *it; ans[event.origin] = *it; } } } } return ans; } };