【路飞】算法与数据结构-供暖器

97 阅读2分钟

不管全世界所有人怎么说,我都认为自己的感受才是正确的。无论别人怎么看,我绝不打乱自己的节奏。喜欢的事自然可以坚持,不喜欢的怎么也长久不了。

LeetCode:原题地址

题目要求

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

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

现在,给出位于一条水平线上的房屋 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

思路

  • 对供暖器排序
  • 遍历房屋,用二分查找找到距离当前房屋最近的左右两边的供暖器
  • 左右任意一个供暖器都可以,故当前距离取左右供暖器距离的较小者
  • 更新半径,要满足所有房间,故半径取当前距离和旧半径的较大者
const findRadius = (houses, heaters) => {
    let r = 0;
    heaters.sort((a, b) => a - b);
    const n = heaters.length;
    for (const house of houses) {
        // 距离当前房屋最近的左供暖器i(可重合)
        const i = search(heaters, house);
        // 右供暖器j
        const j = i + 1;
        // 计算当前房屋离左右供暖器的距离
        const left = i < 0 ? Infinity : house - heaters[i];
        const right = j >= n ? Infinity : heaters[j] - house;
        // 更新半径
        r = Math.max(r, Math.min(left, right));
    }
    return r;
};
const search = (heaters, house) => {
    let [left, right] = [0, heaters.length - 1];
    // 最小的供暖器都在目标房屋的右边
    // 说明房屋左边没有合适的供暖器,用-1代替
    if (heaters[left] > house) return -1;
    while (left < right) {
        // const mid = (left + right) >> 1;
        const mid = ((right - left + 1) >> 1) + left;
        if (heaters[mid] > house) {
            right = mid - 1;
        } else {
            left = mid;
        }
    }
    return left;
};