供暖器

冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。
在加热器的加热半径范围内的每个房屋都可以获得供暖。
现在,给出位于一条水平线上的房屋houses和供暖器heaters的位置,请你找出并返回可以覆盖所有房屋的最小加热半径。
说明:所有供暖器都遵循你的半径标准,加热的半径也一样。

示例

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

题解

/**
 * @param {number[]} houses
 * @param {number[]} heaters
 * @return {number}
 */
var findRadius = function(houses, heaters) {
    houses.sort((a, b) => a - b);
    heaters.sort((a, b) => a - b);
    let max = -Infinity;
    houses.forEach(house => {
        let left = 0, right = heaters.length - 1;
        let tmp = Infinity;
        while(left <= right){
            let mid = (left + right) >> 1;
            if(heaters[mid] === house){
                tmp = 0;
                break;
            }else if(house < heaters[mid]){ // 供热器在房子右侧
                tmp = Math.min(tmp, heaters[mid] - house);
                right = mid - 1;
            }else{ // 供热器在房子左侧
                tmp = Math.min(tmp, house - heaters[mid]);
                left = mid + 1;
            }
        }
        max = Math.max(max, tmp);
    })
    return max;
};

思路

整体思路是遍历房子,找到离每个房子最近的供热器,之后再对比所有离房子最近的供热器,取出其中最长的供热器的范围,就能够使得该固定加热半径的供暖器向所有房屋供暖。首先将房屋位置与供热器位置进行排序,题目中有数据不是顺序排序的,之后定义最大值变量,遍历所有的房屋位置,此处使用二分的方式,将左侧left0,右侧取供热器数量-1作为下标值,当left小于right时进行循环,取得mid为两个指针的中间值,位元算右移一位则相当于除2取整,若是供热器的位置就是房屋位置,那么最短距离为0,返回结束循环,如果供热器在房子右侧,那么取tmp为此时tmp与供热器离房屋距离相比的最小值,并将右指针置为mid - 1,可以举个例子,0 1 2 3 4 5 6全为供热器,假设当遍历的房子在2位置,那么二分第一次取得的供热器是3位置,此时计算后便将右指针从6的指向2,并以此类推,同样如果供热器在房子左侧,那么那么取tmp为此时tmp与供热器离房屋距离相比的最小值,并将左指针置为mid + 1,之后在结束循环后就取得了离该房屋最近的那个供热器的距离,之后取max与当前房屋供热器最近的距离的较大值,在结束外层循环后便取得了所有房屋最近供热器范围中最长的供热器的范围,最后返回该值即可。

每日一题

https://github.com/WindrunnerMax/EveryDay

参考

https://leetcode-cn.com/problems/heaters/