返回

二分双指针:解决供暖器难题

后端

想象这样一个场景:寒冷的冬天,你负责供暖一座拥有 n 个房间的建筑物。每个房间都有一个固定的加热器,位置由数组 heaters 给出。现在,我们希望知道每个房间是否都能被至少一个加热器供暖,且每个加热器的最大供暖范围是 radius。

为了解决这个问题,我们需要利用一个巧妙的算法——二分双指针。

二分查找

二分查找是一种高效的搜索算法,它利用元素的有序性快速定位目标元素。在我们的问题中,我们可以将加热器按位置排序,然后对每个房间进行二分查找,找到离它最近的加热器。

双指针

双指针算法利用两个指针来遍历数据结构。在我们这个场景中,我们可以使用两个指针来遍历加热器数组:

  • left:指向当前房间左侧最近的加热器
  • right:指向当前房间右侧最近的加热器

二分双指针算法

我们将结合二分查找和双指针算法来解决供暖器问题:

  1. 首先,我们将加热器数组按位置排序。
  2. 然后,对于每个房间,我们进行以下操作:
    • 使用二分查找找到房间左侧最近的加热器,并将其保存在 left 中。
    • 使用二分查找找到房间右侧最近的加热器,并将其保存在 right 中。
    • 如果 left 和 right 之间任何加热器的供暖范围都覆盖了当前房间,则该房间会被供暖。

代码示例

def canHeaterCover(heaters, radius, rooms):
    # 排序加热器
    heaters.sort()
    
    # 遍历每个房间
    for room in rooms:
        # 使用二分查找找到左侧最近的加热器
        left = bisect.bisect_left(heaters, room - radius)
        # 如果左侧没有加热器,则房间无法供暖
        if left == 0 or heaters[left - 1] > room + radius:
            return False
        
        # 使用二分查找找到右侧最近的加热器
        right = bisect.bisect_right(heaters, room + radius)
        # 如果右侧没有加热器,则房间无法供暖
        if right == len(heaters) or heaters[right] > room + radius:
            return False
        
    return True

优化

为了进一步优化算法,我们可以使用滑动窗口来代替双指针:

def canHeaterCover(heaters, radius, rooms):
    # 排序加热器
    heaters.sort()
    
    # 使用滑动窗口
    left = 0
    
    # 遍历每个房间
    for room in rooms:
        # 移动 left 指针到右侧最近的加热器
        while left < len(heaters) and heaters[left] < room - radius:
            left += 1
        
        # 如果没有找到右侧最近的加热器,则房间无法供暖
        if left == len(heaters) or heaters[left] > room + radius:
            return False
        
    return True