看到评论区的一个言简意赅的思路:
- 对于每个房屋,要么用前面的暖气,要么用后面的,二者取近的,得到距离;
- 对于所有的房屋,选择最大的上述距离。
第二点很好处理,主要是第一点。第一点的问题在于如何找到房屋前面和后面的暖气。
一个方法是将heaters数组排序,然后进行二分查找。
找到i使得heaters[i] <= house,heaters[i+1] > house。
官方代码如下:
class Solution {
public int findRadius(int[] houses, int[] heaters) {
int ans = 0;
Arrays.sort(heaters);
for (int house : houses) {
int i = binarySearch(heaters, house);
int j = i + 1;
int leftDistance = i < 0 ? Integer.MAX_VALUE : house - heaters[i];
int rightDistance = j >= heaters.length ? Integer.MAX_VALUE : heaters[j] - house;
int curDistance = Math.min(leftDistance, rightDistance);
ans = Math.max(ans, curDistance);
}
return ans;
}
public int binarySearch(int[] nums, int target) {
int left = 0, right = nums.length - 1;
if (nums[left] > target) {
return -1;
}
while (left < right) {
int mid = (right - left + 1) / 2 + left;
if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid;
}
}
return left;
}
}
二分查找思想非常简单,但是具体应用到题目里面细节还是很多的。比如while的条件要不要加等号,left,right更新时候要不要加减1。
就本题的做法来看,二分查找需要找到的是heaters[i] <= house,heaters[i+1] > house。
while循环不带等号,终止条件为left=right。更新left时不+1,保留了搜索到的小于target的nums[mid]。最终得到的是nums[left] = nums[right] <= target 。