执行结果:通过
题目: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(如果没有找到任何房间)。
- 返回结果数组