执行结果:通过
题目: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
代码以及解题思路
代码:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int cmp(const void *a, const void *b) {
int *m = *(int **)a, *n = *(int **)b;
if (m[1] != n[1]) {
return m[1] - n[1];
}
else {
return m[0] - n[0];
}
}
int* closestRoom(int** rooms, int roomsSize, int* roomsColSize, int** queries, int queriesSize, int* queriesColSize, int* returnSize) {
int *res = (int *)malloc(sizeof(int) * queriesSize);
*returnSize = queriesSize;
qsort(rooms, roomsSize, sizeof(int *), cmp);
int left, right;
for (int i = 0; i < queriesSize; i++) {
if (i > 0) { //这个地方优化最后2个测试用例,否则超时
if (queries[i][1] == queries[i - 1][1] && queries[i][0] == queries[i - 1][0]) {
res[i] = res[i - 1];
continue;
}
}
left = 0;
right = roomsSize - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (rooms[mid][1] >= queries[i][1]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
if (right == roomsSize - 1) {
res[i] = -1;
continue;
}
left = right + 1;
right = roomsSize - 1;
int absVal = abs(queries[i][0] - rooms[left][0]);
res[i] = rooms[left][0];
for (int j = left + 1; j <= right; j++) {
int temp = abs(queries[i][0] - rooms[j][0]);
if (temp < absVal) {
absVal = temp;
res[i] = rooms[j][0];
} else if (temp == absVal) {
if (rooms[j][0] < res[i]) {
res[i] = rooms[j][0];
}
}
}
}
return res;
}
解题思路:
- 内存分配 :
- 为结果数组
res
分配内存,其大小为queriesSize
,因为对于每个查询都需要一个结果。 - 通过
*returnSize = queriesSize;
设置返回数组的大小。
- 为结果数组
- 排序 :
- 使用
qsort
函数对rooms
数组进行排序。排序的依据是房间的 y 坐标,如果 y 坐标相同,则按 x 坐标排序。这是为了确保在后续的二分查找中,我们可以快速定位到与查询 y 坐标最接近的房间。
- 使用
- 遍历查询 :
- 对于每个查询,首先检查是否与前一个查询相同(这是为了优化性能,避免对相同的查询进行重复计算)。如果相同,则直接使用前一个查询的结果。
- 使用二分查找定位到
rooms
数组中第一个 y 坐标大于查询 y 坐标的房间的左侧位置(即该位置房间的 y 坐标小于或等于查询的 y 坐标,而下一个位置的 y 坐标大于查询的 y 坐标,或者该位置已经是数组的最后一个元素)。
- 处理边界情况 :
- 如果二分查找的结果指向数组的最后一个元素,并且该元素的 y 坐标仍然小于查询的 y 坐标,则说明没有找到任何符合条件的房间,将结果设置为 -1。
- 在二分查找结果的基础上寻找最接近的房间 :
- 从二分查找确定的左侧位置的下一个位置开始,遍历剩余的房间,找到与查询 x 坐标最接近的房间的 x 坐标。如果有多个房间与查询的 x 坐标距离相同,则选择 x 坐标最小的那个。
- 返回结果 :
- 返回结果数组
res
,其中包含了每个查询对应的最接近房间的 x 坐标或 -1(如果没有找到任何房间)。
- 返回结果数组