475.供暖器

94 阅读1分钟

题目:
冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。

在加热器的加热半径范围内的每个房屋都可以获得供暖。

现在,给出位于一条水平线上的房屋 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
}