得到下标 i 和 j 之后,离房屋 house 最近的供暖器为 heaters}[i] 或 heaters}[j],分别计算这两个供暖器和房屋 house 的距离,其中的最小值即为该房屋需要的供暖器的最小加热半径。对于 i = -1 或 j = n 的下标越界情况,只要将对应的距离设为 +\infty 即可。
publicclassSolution { publicintFindRadius(int[] houses, int[] heaters) { int ans = 0; Array.Sort(heaters); foreach (int house in houses) { int i = BinarySearch(heaters, house); int j = i + 1; int leftDistance = i < 0 ? int.MaxValue : house - heaters[i]; int rightDistance = j >= heaters.Length ? int.MaxValue : heaters[j] - house; int curDistance = Math.Min(leftDistance, rightDistance); ans = Math.Max(ans, curDistance); } return ans; }
publicintBinarySearch(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; } }
[sol1-C++]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution { public: intfindRadius(vector<int> &houses, vector<int> &heaters){ int ans = 0; sort(heaters.begin(), heaters.end()); for (int house: houses) { int j = upper_bound(heaters.begin(), heaters.end(), house) - heaters.begin(); int i = j - 1; int rightDistance = j >= heaters.size() ? INT_MAX : heaters[j] - house; int leftDistance = i < 0 ? INT_MAX : house - heaters[i]; int curDistance = min(leftDistance, rightDistance); ans = max(ans, curDistance); } return ans; } };
[sol1-Python3]
1 2 3 4 5 6 7 8 9 10 11 12
classSolution: deffindRadius(self, houses: List[int], heaters: List[int]) -> int: ans = 0 heaters.sort() for house in houses: j = bisect_right(heaters, house) i = j - 1 rightDistance = heaters[j] - house if j < len(heaters) elsefloat('inf') leftDistance = house - heaters[i] if i >= 0elsefloat('inf') curDistance = min(leftDistance, rightDistance) ans = max(ans, curDistance) return ans
#define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b))
intbinarySearch(constint* nums, int numsSize, int target) { int left = 0, right = numsSize - 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; }
intcmp(constvoid* a, constvoid* b) { int* pa = (int*)a; int* pb = (int*)b; return *pa - *pb; }
intfindRadius(int* houses, int housesSize, int* heaters, int heatersSize){ int ans = 0; qsort(heaters, heatersSize, sizeof(int), cmp); for (int k = 0; k < housesSize; ++k) { int i = binarySearch(heaters, heatersSize, houses[k]); int j = i + 1; int leftDistance = i < 0 ? INT_MAX : houses[k] - heaters[i]; int rightDistance = j >= heatersSize ? INT_MAX : heaters[j] - houses[k]; int curDistance = MIN(leftDistance, rightDistance); ans = MAX(ans, curDistance); } return ans; }
[sol1-Golang]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
funcfindRadius(houses, heaters []int) (ans int) { sort.Ints(heaters) for _, house := range houses { j := sort.SearchInts(heaters, house+1) minDis := math.MaxInt32 if j < len(heaters) { minDis = heaters[j] - house } i := j - 1 if i >= 0 && house-heaters[i] < minDis { minDis = house - heaters[i] } if minDis > ans { ans = minDis } } return }
复杂度分析
时间复杂度:O((n + m) \log n),其中 m 是数组 houses 的长度,n 是数组 heaters 的长度。 对数组 heaters 排序需要 O(n \log n) 的时间。 使用二分查找对每个房屋寻找距离最近的供暖器,每次二分查找需要 O(\log n) 的时间,有 m 个房屋,因此需要 O(m \log n) 的时间。 总时间复杂度是 O((n + m) \log n)。
空间复杂度:O(\log n),其中 n 是数组 heaters 的长度。空间复杂度主要取决于排序所需要的空间。