leetcode
leetcode 1601 ~ 1650
最近的房间

最近的房间

难度:

标签:

题目描述

代码结果

运行时间: 236 ms, 内存: 53.5 MB


/*
 * 思路:
 * 1. 首先,我们需要对房间按照面积进行排序,这样可以快速找到满足面积条件的房间。
 * 2. 然后,我们对每个查询进行处理,找到所有满足面积条件的房间,并选择房间号最接近 preferred 的那个房间。
 * 3. 如果有多个房间号的绝对差值相同,选择房间号最小的那个。
 * 4. 如果没有满足条件的房间,返回 -1。
 */
import java.util.*;
import java.util.stream.Collectors;

public class HotelRoomsStream {
    public int[] closestRoom(int[][] rooms, int[][] queries) {
        List<int[]> roomList = Arrays.stream(rooms)
                .sorted(Comparator.comparingInt(room -> room[1]))
                .collect(Collectors.toList()); // 按面积排序
        int k = queries.length;
        int[] result = new int[k];
        TreeSet<Integer> roomIds = new TreeSet<>(); // 用于快速查找最近的房间号
        int i = 0;

        for (int j = 0; j < k; j++) {
            int preferred = queries[j][0];
            int minSize = queries[j][1];

            // 将所有面积大于等于 minSize 的房间号添加到 TreeSet 中
            while (i < roomList.size() && roomList.get(i)[1] < minSize) {
                i++;
            }
            while (i < roomList.size()) {
                roomIds.add(roomList.get(i)[0]);
                i++;
            }

            // 在 TreeSet 中查找距离 preferred 最近的房间号
            Integer lower = roomIds.floor(preferred); // <= preferred 的最大房间号
            Integer higher = roomIds.ceiling(preferred); // >= preferred 的最小房间号

            if (lower == null && higher == null) {
                result[j] = -1;
            } else if (lower == null) {
                result[j] = higher;
            } else if (higher == null) {
                result[j] = lower;
            } else {
                if (Math.abs(lower - preferred) <= Math.abs(higher - preferred)) {
                    result[j] = lower;
                } else {
                    result[j] = higher;
                }
            }
        }

        return result;
    }
}

解释

方法:

本题解采用排序和二分查找的方法。首先,将房间按照面积从大到小排序,将查询按照最小面积从大到小排序。然后,遍历查询,对于每个查询,使用二分查找在已经满足面积要求的房间中找到最接近期望房间号的房间。具体而言,先二分插入所有满足面积要求的房间号,然后二分查找找到最接近期望房间号的房间。

时间复杂度:

O(m log m + n log n + n log m)

空间复杂度:

O(m + n)

代码细节讲解

🦆
为什么在处理查询前,需要先将房间按面积从大到小排序?
按面积从大到小排序房间是为了在处理查询时更高效地满足面积要求。这种排序方式使得在遍历查询时,可以从最大面积的房间开始添加到可选择列表中,确保一旦房间被添加,所有后续的查询(由于也是按面积要求从大到小排序)都不需要重新检查这些已添加的房间。这样可以避免重复工作,提高整体查询效率。
🦆
排序查询的目的是什么,它是如何帮助优化查找过程的?
查询排序的目的是按照面积需求从大到小对查询进行排序,这样可以确保处理较大面积需求的查询时,已经考虑了所有可能的房间选项。这样的排序配合房间的排序,使得在遍历过程中可以持续维护一个当前符合面积条件的房间列表,而不需要为每个查询重新计算符合条件的房间列表,从而优化整体的查找效率。
🦆
在使用二分查找确定最接近的房间号时,如何处理有多个房间号与预期房间号距离相等的情况?
当存在多个房间号与预期房间号的距离相等时,算法会选择最小的那个房间号。具体实现为,如果二分查找的结果k在已有房间列表中,且k和k-1两个位置的房间号与预期房间号的距离相同,那么选择两者中较小的房间号。这样的处理确保了在距离相等的情况下,结果具有一致的选择偏好,即偏向于房间号较小的选项。
🦆
当`bisect.bisect_left`找到的索引`k`为0或`len(ids)`时,为什么直接选择`ids[0]`或`ids[-1]`作为结果?
当`bisect.bisect_left`返回的索引`k`为0时,意味着所有可选房间的编号都大于预期的房间编号,因此直接选择列表中最小的编号(即`ids[0]`)为最接近的选择。相反,当`k`等于`ids`的长度时,表示所有可选房间的编号都小于预期的房间编号,因此直接选择列表中最大的编号(即`ids[-1]`)为最接近的选择。这种处理方式确保了在极端情况下能够提供一个有效且逻辑上合理的选项。

相关问题