[路飞]_程序员必刷力扣题: 475. 供暖器

261 阅读1分钟

「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战

475. 供暖器

冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。

在加热器的加热半径范围内的每个房屋都可以获得供暖。

现在,给出位于一条水平线上的房屋 houses 和供暖器 heaters 的位置,请你找出并返回可以覆盖所有房屋的最小加热半径。

说明:所有供暖器都遵循你的半径标准,加热的半径也一样。

示例1:

输入: houses = [1,2,3], heaters = [2]
输出: 1
解释: 仅在位置2上有一个供暖器。如果我们将加热半径设为1,那么所有房屋就都能得到供暖。

示例2:

输入: houses = [1,2,3,4], heaters = [1,4]
输出: 1
解释: 在位置1, 4上有两个供暖器。我们需要将加热半径设为1,这样所有房屋就都能得到供暖。

示例3:

输入: houses = [1,5], heaters = [2]
输出: 3

提示:

  • 1 <= houses.length, heaters.length <= 3 * 104
  • 1 <= houses[i], heaters[i] <= 109

排序+二分查找

思路

由题意可知,我们需要求出满足供暖需求的最小半径

其实需要我们求每个房子距离最近的供暖器的最大距离

为了方便查找距离每个房子最近的供暖期的位置,我们这里将供暖期的数组进行排序,然后就可以用二分查找的方式,快速定位供暖期的位置

  • 房子的左右都有供暖器,那么我们需要比较两个供暖器的具体,找出最进的供暖期
  • 房子只有右边有供暖器,那么这就是距离房子最近的供暖期,题目中为了方便查找位置,将左边的距离设置为无穷大
  • 房子只有左边有供暖器,那么这就是距离房子最近的供暖期,题目中为了方便查找位置,将右边边的距离设置为无穷大

具体实现:

  • 对heaters进行sort排序
  • 遍历houses,用findNear函数查找每个房子左侧的供暖期下标left,右侧供暖器下标为left+1
    • 如果房子左侧没有供暖器,那么left = -1,right = 0,最小距离为item-heaters[left]
    • 如果房子左右都有供暖器,那么left和right正常计算,最小距离为item-heaters[left]和heaters[right] - item取最小值
    • 如果房子右侧没有供暖器,那么left = heaters.length - 1,right = heaters.length,最小距离为heaters[right] - item
  • 得到每个房子的最后距离后,取最大值保存在res中

最后返回res即可

var findRadius = function (houses, heaters) {
    let res = 0;
    heaters.sort((a, b) => a - b);
    for (var i = 0; i < houses.length; i++) {
        var item = houses[i]
        var left = findNear(heaters, item);
        var right = left + 1
        var leftDistance = left < 0 ? Number.MAX_VALUE : item - heaters[left];
        var rightDistance = right >= heaters.length ? Number.MAX_VALUE : heaters[right] - item;
        var minDistance = Math.min(leftDistance, rightDistance);
        res = Math.max(res, minDistance);
    }
    return res;
};

var findNear = (nums, target) => {
    let start = 0, end = nums.length - 1;
    if (nums[start] > target) {
        return -1;
    }
    while (start < end) {
        var mid = Math.ceil((start + end) /2);
        if (nums[mid] > target) {
            end = mid - 1;
        } else {
            start = mid;
        }
    }
    return start;
}