LeetCode218:天际线问题

城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。现在,假设您获得了城市风光照片(图A)上显示的所有建筑物的位置和高度,请编写一个程序以输出由这些建筑物形成的天际线(图B)
在这里插入图片描述
个建筑物的几何信息用三元组[Li,Ri,Hi]表示,其中Li和Ri分别是第 i 座建筑物左右边缘的 x 坐标,Hi 是其高度。可以保证0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX和Ri - Li > 0。您可以假设所有建筑物都是在绝对平坦且高度为 0 的表面上的完美矩形。
在这里插入图片描述
在这里插入图片描述

思路
先验知识-堆排序
## 调整大顶堆
# 在已经是堆的情况下进行调整
# i :当前需要调整的节点
# n:还没有排序的节点
def adjst_peap(lists,i,n):
     l = 2*i+1
     r = 2 *i+2
     largest = i
     if l < n and lists[i]<lists[l]:
        largest = l
     if r<n and lists[i]<lists[r]: 
        largest = r
     if largest !=i:
        lists[i],lists[largest]=lists[largest],lists[i]
        # 更新largest的子树
        adjst_peap(lists,largest,n)
      

## 排序
def  sort_peap(lists):
        n = len(lists)
        # build a maxheap
        for i in range(n,-1,-1):
            adjst_peap(lists,i,n)
        
        # 一个个交换元素
        for  i in range(n-1,0,-1):
            lists[0],lists[i]=lists[i],lists[0]
            adjst_peap(lists,0,i)
        return lists

lists = [50,45,40,20,25,35,30,10,15]
print(sort_peap(lists))
处理buildings
  • 维护一个最小堆,记录当前位置下所有的building
  • 将所有的高度取一个反,最小堆的堆顶永远记录着当前位置的最大高度。
  • 将所有的building进行排序,左端点从小到大,高度的负数也从小到大,右端点也从小到大
  • 在上面的所有点坐标的基础上,为每一个building 添加结束坐标 (R,0,0) 表示这个building在这里就结束了。
  • 遍历所有点:
    • 维护一个堆,存放对当前和后面天际线有用的坐标点
    • 每次循环开始,根据当前已到位置,将堆中没有用的点弹出
    • 每次循环,都将当前building的位置加入最小堆
    • 如果最小堆的堆顶坐标高度发生改变,则坐标和高度都记录下来。
from heapq  import heappush,heappop
class Solution(object):
    def getSkyline(self, buildings):
        """
        :type buildings: List[List[int]]
        :rtype: List[List[int]]
        """
        ## 重新保存一下building,left从小到大排列,height 从大到小排列,right 从小到大排序
        # 记录所有可能发生变化的坐标点
        points=[(L,-H,R) for L,R,H in buildings]
        points+=[(R,0,0 )for L,R,H in buildings]
        points.sort()
        
        ## reslut 保存结果
        reslut = [(0,0)]
        ## alive 保存对当前以及后续标注天际线有影响的building
        ## 第一个表示高度,第二个表示building的右边界
        ## alive 作为栈顶表示当前位置高度最高的点
        alive =[(0,float("inf"))]
        for pos,hight,R in points:
            while alive[0][1]<=pos:
                # 将不会影响后面天际线的building弹出
                # alive 是最小堆的根节点
                heappop(alive)
            if hight:
                # 将新加入的building加入堆中
                heappush(alive,(hight,R))
            if reslut[-1][1]!=-alive[0][0]:
                reslut+=[[pos,-alive[0][0]]]
        return reslut[1:]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值