今天的困难题没啥思路,在此记录一下对官方题解的理解。
题目
思路
利用扫描线来做本题,为了优化算法的时间复杂度,使用优先队列存储当前的最大高度。
算法步骤:
- 首先是对所有建筑的
边界x坐标值
进行存储和排序,得到升序列表bound_x
; - 对
bound_x
中的元素i
开始遍历,因为buildings
中的数据是按照left的值非严格递增
排列的,所以每次不用循环遍历buildings中所有的元素; - 将
left小于i
的buildings[indx]对应的right和height存入优先队列p
中; - 如果
i大于等于优先队列的队头元素的right值
,则循环出队
(因为只需要得到左侧的信息,所以这样的点已经没用了); - 如果
当前队列的最大高度
等于当前结果集最后一个元素中的高度值
,则证明当前结果集最后一个元素是该平面的最左侧点
,所以舍弃当前的坐标点
; - 最后返回结果集res;
下面以示例1的数据为例,仔细分析代码的计算过程:
bound_x | 2 | 3 | 5 | 7 | 9 | 12 | 15 | 19 | 20 | 24 |
---|---|---|---|---|---|---|---|---|---|---|
index | 0 | 1 | 2 | 3 | 3 | 3 | 3 | 4 | - | - |
添加数据后的有限队列p | (9,10) | (7,15)(9,10) | (7,15)(12,12)(9,10) | (7,15)(12,12)(9,10) | (12,12)(9,10) | (12,12)(9,10) | (20,10) | (20,10)(24,8) | (20,10)(24,8) | (24,8) |
删除数据后的有限队列p | (9,10) | (7,15)(9,10) | (7,15)(12,12)(9,10) | (12,12)(9,10) | (12,12)(9,10) | - | (20,10) | (20,10)(24,8) | (24,8) | - |
当前p中数据的最大高度 | 10 | 15 | 15 | 12 | 12 | 0 | 10 | 10 | 8 | 0 |
结果集res中上一个元素的高度 | 0 | 10 | 15 | 15 | 12 | 12 | 0 | 10 | 10 | 8 |
结果集res(只显示添加的过程) | (2,10) | (3,15) | - | (7,12) | - | (12,0) | (15,10) | - | (20,8) | (24,0) |
所以结果集res的结果为[[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
代码–对官方题解的代码添加了注释
public List<List<Integer>> getSkyline(int[][] buildings) {
//存储所有的x坐标
List<Integer> bound_x = new ArrayList<>();
for (int[] i : buildings)
{
bound_x.add(i[0]);
bound_x.add(i[1]);
}
Collections.sort(bound_x);
int index = 0;
int len = buildings.length;
//存储最终答案
List<List<Integer>> res = new ArrayList<>();
//存所有的右上边界点信息,高度值大的位于队列头部
PriorityQueue<int[]> p = new PriorityQueue<>((a,b)->b[1]-a[1]);
for (int i : bound_x)
{
//因为buildings的信息是按buildings[x][0]的值非严格递增排序的,所以每次不用遍历所有的信息
while (index<len && buildings[index][0]<=i)
{
p.add(new int[]{buildings[index][1],buildings[index][2]});
index++;
}
//如果当前队列中头部的x坐标小于当前的x坐标,无论其高度,都舍弃掉
while(!p.isEmpty() && p.peek()[0] <= i)
p.poll();
//获取当前队列的最大高度
int curMaxHeight = p.isEmpty()?0:p.peek()[1];
//如果结果集为空或结果集中上一个坐标的高度不等于当前队列的最大高度,则在结果集添加
if (res.size()==0 || curMaxHeight != res.get(res.size()-1).get(1))
res.add(Arrays.asList(i,curMaxHeight));
}
return res;
}