题目描述
一个酒店里有 n
个房间,这些房间用二维整数数组 rooms
表示,其中 rooms[i] = [roomId_i, size_i]
表示有一个房间号为 roomId_i
的房间且它的面积为 size_i
。每一个房间号 roomId_i
保证是 独一无二 的。
同时给你 k
个查询,用二维数组 queries
表示,其中 queries[j] = [preferred_j, minSize_j]
。第 j
个查询的答案是满足如下条件的房间 id
:
- 房间的面积 至少 为
minSize_j
,且 abs(id - preferred_j)
的值 最小,其中abs(x)
是x
的绝对值。
如果差的绝对值有 相等 的,选择 最小 的 id
。如果 没有满足条件的房间,答案为 -1
。
请你返回长度为 k
的数组 answer
,其中 answer[j]
为第 j
个查询的结果。
样例
输入: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。
输入: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 <= 10^5
k == queries.length
1 <= k <= 10^4
1 <= roomId_i, preferred_j <= 10^7
1 <= size_i, minSize_j <= 10^7
算法
(排序,有序集合) $O((n + k) \log n)$
- 将房间按照
size
从大到小排序;将询问也按size
从大到小排序。 - 维护一个有序集合。
- 对于每个询问,更新可用的房间的编号,然后通过在有序集中
lower_bound
找到最接近preferred
的房间。
时间复杂度
- 排序的时间复杂度为 $O(n)$。
- 遍历时,每个房间会被加入到有序集合中一次。对于每个询问也会被查询一次,故总时间复杂为 $O((n + k) \log n)$。
空间复杂度
- 需要 $O(n)$ 的额外空间存储排序时的系统栈和有序集合。
C++ 代码
class Solution {
public:
vector<int> closestRoom(vector<vector<int>>& rooms, vector<vector<int>>& queries) {
sort(rooms.begin(), rooms.end(),
[](const vector<int> &r1, const vector<int> &r2) {
return r1[1] > r2[1];
}
);
const int k = queries.size();
vector<int> idx(k);
for (int i = 0; i < k; i++)
idx[i] = i;
sort(idx.begin(), idx.end(), [&](int q1, int q2) {
return queries[q1][1] > queries[q2][1];
});
const int n = rooms.size();
set<int> s;
vector<int> ans(k);
for (int i = 0, j = 0; i < k; i++) {
int pref = queries[idx[i]][0], mins = queries[idx[i]][1];
while (j < n && rooms[j][1] >= mins) {
s.insert(rooms[j][0]);
j++;
}
if (s.empty()) {
ans[idx[i]] = -1;
continue;
}
auto it = s.lower_bound(pref);
int ma = -1, mi = -1;
if (it != s.end()) ma = *it;
if (it != s.begin()) --it;
mi = *it;
if (ma == -1) ans[idx[i]] = mi;
else if (mi == -1) ans[idx[i]] = ma;
else {
if (pref - mi <= ma - pref) ans[idx[i]] = mi;
else ans[idx[i]] = ma;
}
}
return ans;
}
};