边工作边刷题:70天一遍leetcode: day 94

The Skyline Problem

要点:这题是难题,但是是重点难题,因为google常考,而且很多变形。题本身的pattern就是从左到右更新区间内存在值的最大值(对于这题就是skyline)。最简单的解法就是从左到右根据每个区间的enter/exit point更新存在值的集合。 同时因为区间值集合是不断变化的,需要有个data structure来track当前最大值,priority queue和tree map都可以。
实现上还有不少细节

  • priority queue中元素类型?一个integer就够了
  • compare function:等于?
    • 注意这个compare function是对时间点sort时候用的,而不是priority queue的,priority queue只根据height来排序
  • 输入输出

补充更好的方法(更简单,并且beat 98.2% python)

  • 因为building已经按start排好了,不用再排序。heap的最大height就是当前iteration的skyline。当然可能当前的height和当前skyline相同,不更新,这个code的结构就非常简单。
  • 如何定义当前iteration?每个新的start和当前在heap的最大height的end做比较,两个分支:
    • 新的start的存在并且<=heap顶的end,这时候push(push要在loop里把所有start的都push进去,heap顶end也要push)
    • 1的reverse:没新start了,或者新start有空隙。这时候当前iteration就是考虑当前skyline的end(也就会上轮heap的最大值)。pop也是在loop里,把所有已经结束的段pop出来。
    • x: either next start or current end, so it’s in skyline
  • 综上,总循环就是i<n or heap有值
  • 边界条件:
    • 如果start和heap顶end相同,那么push,因为这样height是连续下去的
    • push的时候,多个start相同,要全部push,因为以最大的height为准
    • pop的时候要pop所有dead end:所以第二维也要按最大排序,这样height相同的时候保证end大的作为标准
class Solution(object):
    def getSkyline(self, buildings):
        """
        :type buildings: List[List[int]]
        :rtype: List[List[int]]
        """
        LRH = buildings
        i, n = 0, len(buildings)
        skyline = []
        liveHR = []
        while i<n or liveHR:
            if not liveHR or i<n and LRH[i][0]<=-liveHR[0][1]:
                x = LRH[i][0]
                while i<n and LRH[i][0]==x:
                    heapq.heappush(liveHR, (-LRH[i][2], -LRH[i][1]))
                    i+=1
            else:
                x = -liveHR[0][1]
                while liveHR and -liveHR[0][1]<=x:
                    heapq.heappop(liveHR)
            
            height = len(liveHR) and -liveHR[0][0]
            if not skyline or skyline[-1][1]!=height:
                skyline.append([x, height])
        return skyline
                
posted @ 2016-04-09 06:20  absolute100  阅读(98)  评论(0编辑  收藏  举报