题目

类型:双指针
image.png

解题思路

需要求得最小加热半径 ans,使得所有的 houses[i] 均被覆盖。

在以 ans 为分割点的数轴上具有「二段性」:

  • 数值小于 ans 的半径无法覆盖所有的房子;
  • 数值大于等于 ans 的半径可以覆盖所有房子。

因此可直接「二分答案」,考虑应该在什么范围内进行「二分」。
可以从数据范围入手,使用 1e9 为二分上界,该做法能确保答案在二分范围内。
考虑如何实现 check 函数。
先对 houses 和 heaters 进行排序,使用 i 指向当前处理到的 houses[i];j 指向可能覆盖到 houses[i] 的最小下标 heaters[j];x 代表当前需要 check 的半径。
当且仅当 heaters[j] + x < houses[i] 时,houses[i] 必然不能被 heaters[j] 所覆盖,此时让 j 自增。
找到合适的 j 之后,再检查heaters[j]−x <= houses[i] <= heaters[j]+x是否满足,即可知道 houses[i] 的覆盖情况。

代码

  1. class Solution {
  2. public int findRadius(int[] houses, int[] heaters) {
  3. Arrays.sort(houses);
  4. Arrays.sort(heaters);
  5. int l = 0, r = (int) 1e9;
  6. while (l < r) {
  7. int mid = l + r >> 1;
  8. if (check(houses, heaters, mid)) {
  9. r = mid;
  10. } else{
  11. l = mid + 1;
  12. }
  13. }
  14. return r;
  15. }
  16. boolean check(int[] houses, int[] heaters, int x) {
  17. int n = houses.length, m = heaters.length;
  18. for (int i = 0, j = 0; i < n; i++) {
  19. while (j < m && houses[i] > heaters[j] + x) j++;
  20. if (j < m && heaters[j] - x <= houses[i] && houses[i] <= heaters[j] + x) continue;
  21. return false;
  22. }
  23. return true;
  24. }
  25. }