题目:
冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。
在加热器的加热半径范围内的每个房屋都可以获得供暖。
现在,给出位于一条水平线上的房屋 houses 和供暖器 heaters 的位置,请你找出并返回可以覆盖所有房屋的最小加热半径。
说明:所有供暖器都遵循你的半径标准,加热的半径也一样
算法:
1.想当然了,两个入参都不是有序的。
2.right < houses[h]的情况要讨论清楚,不能直接判断为后续所有供暖器都无法覆盖到。
3.二分查找本质上是猜测,猜一个半径,看能不能覆盖到所有房屋。如果不能则猜一个更大的半径,如果能覆盖则把猜一个更大的半径。然后实现检测函数,检测某一个半径能否覆盖到所有房屋。
方法一:二分查找法
func findRadius(houses []int, heaters []int) int {
// 供暖半径[0,len(houses)],heater和房子坐标重叠时,供暖半径为0即可
// sort.Slice(heaters, func(i, j int) bool {return heaters[i] < heaters[j]})
sort.Ints(houses)
sort.Ints(heaters)
left, right := 0, max(houses[len(houses) - 1], heaters[len(heaters) - 1])
for left < right {
mid := (left + right) / 2
res := coverAllHouse(houses, heaters, mid)
if res {
right = mid
} else {
left = mid + 1
}
}
return left
}
func coverAllHouse(houses []int, heaters []int, r int) bool {
// 供暖覆盖的最左侧和最右侧的房子
index := 0
left, right := heaters[0] - r, heaters[0] + r
for h := range houses {
if left <= houses[h] && houses[h] <= right {
continue
}
// 当前供暖期无法覆盖,遍历后面所有的供暖期有能覆盖到当前房屋吗
// 不能查看下一个供暖器
index ++
found := false
for ;index < len(heaters); index ++ {
left = heaters[index] - r
right = heaters[index] + r
if left <= houses[h] && houses[h] <= right {
found = true
break
}
// houses[h] < left ,后面不可能还有供暖器覆盖到了
if houses[h] < left {
return false
}
// 如果 right < houses[h],还可以往后找有没有供暖器覆盖到
}
if !found {
return false
}
}
return true
}
func max(a, b int) int {
if a > b {
return a
}
return b
}