扫描线
lintcode391. 数飞机
题目
给出飞机的起飞和降落时间的列表,用 interval 序列表示. 请计算出天上同时最多有多少架飞机?
样例
对于每架飞机的起降时间列表:
[[1,10],[2,3],[5,8],[4,7]]
, 返回3
。
分析
计算空中的飞机个数,可以看成用一个线从左到右扫描的过程,计算每一时刻空中飞机的数量。
优化:只计算所有线段起始位置时天上的飞机即可,因为只有起始点是可能发生变化的点。遇到起点,天上的飞机数+1,遇到终点则-1。
因此,我们先将所有线段的起点、终点排序,并标记是起点还是终点,然后从小到大遍历这些点,遇到起点则+1,遇到终点-1,返回过程中最大的数值即为空中飞机数的最大值。
需要注意的是:在同一点上会同时有开始点和结尾点,此时应该把结尾点放在前面,否则会出现多计算的情况。
代码
|
252.Meeting Rooms
题目
Given an array of meeting time intervals consisting of start and end times
[[s1,e1],[s2,e2],...]
(si < ei), determine if a person could attend all meetings.For example,
Given[[0, 30],[5, 10],[15, 20]]
,
returnfalse
.
思路
题目是说判断一个人是否可以参加给出的所有的会议,可以沿用扫描线的思路:同一时刻最多只有一个会议正在召开,就可以参加所有会议。
还有另外一种更快的思路:
如果每一个会议的开始都在上一个会议结束之后,那么就不会有时间冲突的会议,就可以都参加了,所以可以将给出的所有会议的开始时间和结束时间分别放入两个数组中,分别排序,然后判断是否所有的时间满足:starts[i]>ends[i-1]。
代码
|
253.Meeting Rooms II
题目
Given an array of meeting time intervals consisting of start and end times
[[s1,e1],[s2,e2],...]
(si < ei), find the minimum number of conference rooms required.For example,
Given[[0, 30],[5, 10],[15, 20]]
,
return2
.
给定一系列会议的开始和结束时间,返回所需的最大会议室数量
分析
方法一:
用扫描线模拟扫描过程,计算扫描线最多同时扫描几个区间。
方法二:
分别对会议开始和结束的时间排序,两个指针ij分别指向开始数组和结束数组,当start[i] < end[j]时,i++;sum++;
否则j++,记录最大的sum。
代码
方法一:
|
方法二:
|
218.The Skyline Problem
题目
A city’s skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skyline formed by these buildings collectively (Figure B).
The geometric information of each building is represented by a triplet of integers
[Li, Ri, Hi]
, whereLi
andRi
are the x coordinates of the left and right edge of the ith building, respectively, andHi
is its height. It is guaranteed that0 ≤ Li, Ri ≤ INT_MAX
,0 < Hi ≤ INT_MAX
, andRi - Li > 0
. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.For instance, the dimensions of all buildings in Figure A are recorded as:
[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ]
.The output is a list of “key points“ (red dots in Figure B) in the format of
[ [x1,y1], [x2, y2], [x3, y3], ... ]
that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.For instance, the skyline in Figure B should be represented as:
[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]
.
题目给定每一个建筑的起始结束位置和其高度,返回建筑物构成的轮廓的拐点坐标。
分析
根据观察,可以用扫描线的思路解决。
首先需要将建筑物的开始和结束节点及其对应的高度加入堆heap中,按照坐标从小到大进行排序,当坐标一致的时候,将结束点排在前面。
另外,还需要一个堆heightTemp来维护当前扫描线扫过的建筑的高度,以便迅速知道当前的最大高度。
接下来,将节点依次出堆模拟扫描线扫描的过程,分下面两种情况:
- 遇到起始点:
- 该点的高度大于当前最大高度,需要将该点坐标以及高度加入结果集,同时将高度加入heightTemp
- 该点的高度不大于当前最大高度,则只需将该点高度加入heightTemp,无需加入结果集。
- 遇到结束点:
- 该点高度就是当前最大高度,则需要将最大高度从heightTemp中pop出去,然后将该点坐标和pop之后的当前最大高度加入结果集。
- 该点高度小于当前最大高度,只需将该点高度从heightTemp中pop出去。
实现上面的算法之后,还不够,因为忽略了在同一个位置有多个点出现的情况,比如某个位置即是A建筑的结束也是B建筑的开始位置,将它们都加入的结果集,显然是重复的,需要筛选掉只剩一个,分如下两种情况:
- 在某个点有多个建筑结束 —> 取最后一个结束的,也就是高度最低的
- 在某个点有多个建筑开始 —> 取高度最高的
- 在某个点既有建筑开始也有建筑结束,但前后高度不一样 —> 取开始高度最高的
- 在某个点既有建筑开始也有建筑结束,但前后高度一样 —> 不加入最终结果集
基于上面的思路,可以开始写代码了
据说这道题还可以用线段树做,待学习。。。
代码
|