[前端]_一起刷leetcode 475. 供暖器

196 阅读3分钟

这是我参与2022首次更文挑战的第15天,活动详情查看: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

思路

  1. 我们可以对房屋和供暖器先做一轮排序,然后对于每个房屋,要么用前面的暖气,要么用后面的,二者取近的,得到距离;
  2. 一开始我们的半径是0,当我们的最近距离大于我们的半径的时候,我们的半径要扩大成当前的最近距离;
  3. 我们可以通过一轮遍历,每次判断房屋是离当前的供暖器比较近还是下一个比较近,同时我们用一个索引hIndex来记录我们当前用的是哪个供暖器;
  4. 最终遍历结束后我们统计出来的结果就是最小值了。

实现

/**
 * @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 hIndex = 0; // 记录供暖器的位置
    let r = 0; // 半径的长度

    // 枚举所有的房屋
    for (let i = 0; i < houses.length; i++) {
        // 如果后面还有供暖器, 并且后面的供暖器近就把供暖器的位置往后移动一个位置
        if (hIndex < heaters.length - 1 
            && Math.abs(heaters[hIndex + 1] - houses[i]) < Math.abs(heaters[hIndex] - houses[i])) {
            hIndex++;
        }

        // 这里不能简写,因为我们不确定是否拥有heaters[hIndex + 1],这个值会变化的
        r = Math.max(r, Math.abs(heaters[hIndex] - houses[i]));
    }

    return r;
};

翻车

image.png

分析原因,为什么我们算出来的答案跟实际的不相符。其实是因为我们这样子统计,只能比较当前的供暖器和下一个供暖器之间的大小关系,实际上我们需要比较的是后面所有比之大的,所以这个地方我们不能用if来单纯判断当前和下一个,而是要用while来不断做判断直到找到为止。

最终代码

/**
 * @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 hIndex = 0; // 记录供暖器的位置
    let r = 0; // 半径的长度

    // 枚举所有的房屋
    for (let i = 0; i < houses.length; i++) {
        // 如果后面还有供暖器, 并且后面的供暖器近就把供暖器的位置往后移动一个位置
        while (hIndex < heaters.length - 1 
            && Math.abs(heaters[hIndex + 1] - houses[i]) <= Math.abs(heaters[hIndex] - houses[i])) {
            hIndex++;
        }

        r = Math.max(r, Math.abs(heaters[hIndex] - houses[i]));
    }

    return r;
};

结果

image.png

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。