题目链接 : https://leetcode.com/problems/the-skyline-problem/
解题思路
先定义下:对于三元组(left,right,high)
我们可以认为(left,high)为开始的先计为(left,high,true)
(right,high) 认为结束的点,计为(right,high,false),把数据整理为如上格式之后,把输入的点处理一下,保证排顺序如下:
1.left 小的优先;
2.left相同,开始的点优先;
3.同为开始点或者结束点,则要分情况处理,对于开始点high大的优先;对于结束点high小的优先;
我们借助优先队列,保存之前出现的过的高度,遍历到开始点的时候需要加入队列,遍历到结束点的时候需要从队列中删除。
下一步进行点的遍历,分为两种情况:
如果是开始点则要看该点高度是否大于堆顶高度,如果大于则记录下来,如果没有则说明之前出现过在该点左边的且比该点高的点,所以该点是被隐藏的,不是我们需要的结果。
如果是结束点,意味着这个点产生的高度要结束啦,如果产生的高度就是最大高度,则我们需要该点的横坐标和优先队列中的第二大高度生成的点;
如果该点不是最大高度的点,则说明之前出现比高点还要高的点,且还没有结束,所以该点是被隐藏的,直接删除即可。
下面给出代码:
static class Point implements Comparable<Point>{
int x;
int h;
boolean start;
Point(int x,int h,boolean start) {
this.x = x;
this.h = h;
this.start = start;
}
@Override
public int compareTo(Point other) {
if (this.x != other.x) {
return this.x - other.x;
} else if (this.start != other.start){
return this.start ? -1 : 1;
} else if (this.start) {
return other.h - this.h;
} else {
return this.h - other.h;
}
}
}
private List<Point> genPoints(int[][]buildings) {
List<Point> points = new ArrayList<>(buildings.length * 2);
for (int[]building : buildings) {
points.add(new Point(building[0],building[2],true));
points.add(new Point(building[1],building[2],false));
}
Collections.sort(points);
return points;
}
public List<int[]> getSkyline(int[][] buildings) {
List<Point> points = genPoints(buildings);
List<int[]> result = new ArrayList<>();
Queue<Integer> highPriQueue = new PriorityQueue(Collections.reverseOrder());
for(Point p : points) {
if (p.start) {
if (highPriQueue.isEmpty() || p.h > highPriQueue.peek()) {
result.add(new int[]{p.x,p.h});
}
highPriQueue.add(p.h);
} else {
int curMaxH = highPriQueue.peek();
if (p.h == curMaxH) {
highPriQueue.poll();
if (highPriQueue.isEmpty() || curMaxH != highPriQueue.peek()) {
int curH = highPriQueue.isEmpty() ? 0 : highPriQueue.peek();
result.add(new int[]{p.x,curH});
}
} else {
highPriQueue.remove(p.h);
}
}
}
return result;
}
public static void main(String[] args) {
SkylineProblem skylineProblem = new SkylineProblem();
skylineProblem.getSkyline(
new int[][]{{1,2,1},{1,2,2},{1,2,3}});
}