Leetcode218 天际线问题/探索卡片/学渣のday1

Leetcode 探索 day 1

  • 天际线问题

天际线问题

今天开始记录学习leetcode的过程。首先是探索卡片“Teambition”.第一题呢就是天际线问题。
天际线问题
看完题目,显而易见得不会做。那么先去搜下别人的题解(searching…)
15min 后,没看懂其他人博客里解释的QAQ…
但是从leetcode的标准答案里找了个带注释的,贴上来观摩一番:

class Solution():
    def getSkyline(self, buildings):
        x = (list(set([i[0] for i in buildings] + [i[1] for i in buildings])))
        x.sort()
        index = 0
        heap = []
        r = [[-1,0]]
        for i in x:#以x坐标上的点为循环条件。
            #遍历所有的建筑物,找到最左边端点小于i的建筑。index没有置0
            while index < len(buildings) and buildings[index][0] <= i:
                #python内置的为小顶堆,所以高度加负号
                heapq.heappush(heap,(-buildings[index][2],buildings[index][1]))
                index += 1
                #高度最高的建筑的右边,结束的边界可以去掉它了
            while heap and heap[0][1]<= i:
                heapq.heappop(heap)
            #将最高的高度保持
            h = -heap[0][0] if heap else 0
            if h != r[-1][1]:#是否和保存的上一个点在一条直线上。
                r.append([i,h])#保存的是关键点
        return r[1:]

第一行是干嘛呢,输出一下:
输入:[[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
输出:[2,3,5,7,9,12,15,19,20,24]
好的,这是把所有起点和终点都不分贫富贵贱的排在了一块。不用先set再list,直接
x = [i[0] for i in buildings] + [i[1] for i in buildings]就完事了

第二行排序。必须要的,删掉报error。至于为啥要排序,再往下看;
声明了个index和一个堆,接着看;
r里存了个[-1,0],完全不知道想干嘛目前;

以x遍历来了来了,while index < len(buildings) and buildings[index][0] <= i:
(注释的那句看不懂在讲什么??)既然index < len(buildings) 这么判断了,index就是建筑标号。
buildings[index][0] <= i就是找左端点在i(i是所有端点集合中的点)之前的建筑。ok继续;

堆里存放满足条件的建筑的右端点和它的高度(取负变成大顶堆);
while heap and heap[0][1]<= i:当heap不为空,也就是之前找到的建筑中最高的,并且它的右端点也小于i了。就把它pop出来。为什么可以pop了呢,八成是因为后面用不到了吧,思考ing。。。

2min后,还是不理解(凉了凉了)继续看吧。

好了,h是现在最高的建筑的高度,如果heap为空那么就是0了。
然后判断,是否和保存的上一个点在一条直线上(???),不是的话,r保存i(横坐标),h(纵坐标)

最后返回r,从第一个开始(???)

看完代码满心疑惑,那么用简单的测试样例过一遍看看。(学渣の挣扎)
输入:[[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
x = [2,3,5,7,9,12,15,19,20,24]
r=[[-1,0]]
index=0
len(buildings)=5
i=2:
0<5 and 2<=2:
h.push(-10,9)
1<5 but 3 >2:break
h but 9>2:break
h = 10
if h !=0:
r.append([2,10])
这里可以理解的是,r[1:]是因为一开始存了个init数据防止r[-1]溢出.
i=3:
1<5 and 3<=3:
h.push(-15,7)
2<5 but 5>3:break
h but 7>3:break
h = 15
if h !=10:
r.append(3,15)
这里可以理解的是,为什么要做if h != r[-1][1]的判断,如果这次不是15也是10,那么就是一条水平线上,不是要求的端点了,因为是大顶堆,不可能拿到小于10的。
i=5:h.push(-12,12)
这里可以稍微理解一下while heap and heap[0][1]<= i的判断了,如果最高楼的右边已经小于i了,说明他的两个端点都被考虑过了,不可能再出现在r里,要让位给年轻人了(???你在说什么)
i = 7:
h.pop(-15,7)
h=12
12!=15
r.append(7,12)
这里就是第二座楼,又名珠穆朗…15,右端点已经扫过了,就退出,让小三[5,12,12]上位。
直到小三的右端点也扫过了,也就是到12的时候,heap就空了,这时候h = -he[0][0] if heap else 0
h变为0,终于家破人亡了(???)好了,这时候r.append(12,0).这样,一组爱恨纠缠的楼群就算完事了。后面碰到新的又是重复这个过程。直到遍历结束。

(以上过程配合题目中的图示食用更佳)

看了下时间,居然过去70分钟了???学渣の悲哀

接下来就是把代码自己默写一遍(coding…)

OK!!!经过大概修改了七八个笔误和一两个语法错误之后,我耗时约12min,靠自己(默写) AC了Leetcode218。
最后还有必要总结一下么emmmmm,算了,都AC了还水啥呢。过了过了

你可能感兴趣的:(leetcode探索)