题目描述:
冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。
在加热器的加热半径范围内的每个房屋都可以获得供暖。
现在,给出位于一条水平线上的房屋 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 排序,然后通过二分查或双指针找得到距离最近的供暖器即可。
时间复杂度:O((n + m)log n)),其中 m 是数组 houses 的长度,n 是数组heaters 的长度。
- 对数组 heaters 排序需要 O(nlog n)的时间。
- 使用二分查找对每个房屋寻找距离最近的供暖器,每次二分查找需要 O(log n)的时间,有 m 个房屋,因此需要 O(mlog n)) 的时间。 总时间复杂度是 O((n + m)log n))。
编码:
class Solution {
public int findRadius(int[] houses, int[] heaters) {
int ans = 0;
//首先对heaters数组排序
Arrays.sort(houses);
Arrays.sort(heaters);
//遍历houses,找出每个house所需的最小加热半径
for(int house : houses){
//结果即为所有加热半径中的最大值
ans = Math.max(ans, distance(house, heaters));
}
return ans;
}
public int distance(int h, int[] heaters){
if(heaters.length == 1){
return Math.abs(heaters[0] - h);
}
int left = 0;
int right = heaters.length - 1;
while(left <= right){
int mid = (left + right) >> 1;
if(heaters[mid] > h){
right = mid - 1;
} else if(heaters[mid] == h){
return 0;
} else{
left = mid + 1;
}
}
if(left == 0){
return(heaters[0] - h);
}
if(left == heaters.length){
return(h - heaters[heaters.length - 1]);
}
return Math.min(heaters[left] - h, h - heaters[left - 1]);
}
}