方法1: 这道题目目前是超过了我的能力范围的,不论是在数据结构的使用还是逻辑的理解上来说都是比较难的。这边我建议复盘的时候看这个视频,讲得很清楚,然后看完了,自己写一遍,现在我自己是没去实现的,因为感觉太难了,做了意义不大。然后记得还要去分析复杂度。
class Solution {
private class Point implements Comparable<Point>{
private int x;
private int height;
private boolean isStart;
public Point(int x, int height, boolean isStart) {
this.x = x;
this.height = height;
this.isStart = isStart;
}
// 比较规则复杂,主要是考虑到了三种边界情况
public int compareTo(Point p) {
if (this.x != p.x) {
return this.x - p.x;
} else {
if (this.isStart && p.isStart) {
return p.height - this.height;
}
if (!this.isStart && !p.isStart) {
return this.height - p.height;
}
return this.isStart?-1:1;
}
}
}
public List<List<Integer>> getSkyline(int[][] buildings) {
int len = buildings.length;
if (len == 0 || buildings[0].length == 0) {
return new ArrayList<List<Integer>>();
}
// 每栋建筑有两个关键点
Point[] points = new Point[len * 2];
int index = 0;
// 初始化所有关键点的数组
for (int[] building : buildings) {
int start = building[0];
int end = building[1];
int h = building[2];
points[index++] = new Point(start,h,true);
points[index++] = new Point(end,h,false);
}
// 将这些点按照我们希望的顺序排序
Arrays.sort(points);
// 用Collections.reverseOrder()来建立大根堆,这样就可以找到当前最高的高度
PriorityQueue<Integer> queue = new PriorityQueue<>(Collections.reverseOrder());
queue.offer(0);
List<List<Integer>> res = new ArrayList<>();
int prevMaxVal = 0;
for (Point point : points) {
if (point.isStart) {
queue.offer(point.height);
int curMaxVal = queue.peek();
// 如果最大值变化了(只能变大),就说明这个点应该被记录
if (curMaxVal > prevMaxVal) {
List<Integer> l = new ArrayList<>();
l.add(point.x);
l.add(point.height);
res.add(l);
prevMaxVal = curMaxVal;
}
} else {
queue.remove(point.height);
int curMaxVal = queue.peek();
// 最大值变化了(只能变小),记录当前点
if (curMaxVal < prevMaxVal) {
List<Integer> l = new ArrayList<>();
l.add(point.x);
l.add(curMaxVal);
res.add(l);
prevMaxVal = curMaxVal;
}
}
}
return res;
}
}
总结:
- 无