城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回由这些建筑物形成的 天际线 。
每个建筑物的几何信息由数组 buildings 表示,其中三元组 buildings[i] = [ l e f t i left_i lefti, r i g h t i right_i righti, h e i g h t i height_i heighti] 表示:
- l e f t i left_i lefti 是第 i 座建筑物左边缘的 x 坐标。
- r i g h t i right_i righti 是第 i 座建筑物右边缘的 x 坐标。
- h e i g h t i height_i heighti 是第 i 座建筑物的高度。
天际线 应该表示为由 “关键点” 组成的列表,格式 [[x1,y1],[x2,y2],…] ,并按 x 坐标 进行 排序 。关键点是水平线段的左端点。列表中最后一个点是最右侧建筑物的终点,y 坐标始终为 0 ,仅用于标记天际线的终点。此外,任何两个相邻建筑物之间的地面都应被视为天际线轮廓的一部分。
注意:输出天际线中不得有连续的相同高度的水平线。例如 […[2 3], [4 5], [7 5], [11 5], [12 7]…] 是不正确的答案;三条高度为 5 的线应该在最终输出中合并为一个:[…[2 3], [4 5], [12 7], …]
优先队列排序当前最大高度
class Solution {
class Point {
int x;
int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
public List<List<Integer>> getSkyline(int[][] buildings) {
List<Point> points = new ArrayList<>();
for (int i = 0; i < buildings.length; i++) {
Point p1 = new Point(buildings[i][0], -buildings[i][2]);
Point p2 = new Point(buildings[i][1], buildings[i][2]);
points.add(p1);
points.add(p2);
}
Collections.sort(points, new Comparator<Point>() {
@Override
public int compare(Point p1, Point p2) {
if (p1.x != p2.x)
return p1.x - p2.x;
else
return p1.y - p2.y;
}
});
Queue<Integer> heights = new PriorityQueue<>((h1, h2) -> h2 - h1);
heights.offer(0);
int curHeight = 0;
List<List<Integer>> result = new ArrayList<>();
for (Point p : points) {
if (p.y < 0)
heights.offer(-p.y);
else
heights.remove(p.y);
if (curHeight != heights.peek()) {
curHeight = heights.peek();
List<Integer> point = new ArrayList<>();
point.add(p.x);
point.add(curHeight);
result.add(point);
}
}
return result;
}
}
归并
class Solution {
public List<List<Integer>> getSkyline(int[][] buildings) {
int len = buildings.length;
if(len == 0)
return new ArrayList<>();
return merge(buildings, 0, len - 1);
}
private List<List<Integer>> merge(int[][] buildings, int start, int end) {
List<List<Integer>> result = new ArrayList<>();
if (start == end) {
List<Integer> point = new ArrayList<>();
point.add(buildings[start][0]);
point.add(buildings[start][2]);
result.add(point);
point = new ArrayList<>();
point.add(buildings[start][1]);
point.add(0);
result.add(point);
return result;
}
int mid = (start + end) / 2;
List<List<Integer>> skyline1 = merge(buildings, start, mid);
List<List<Integer>> skyline2 = merge(buildings, mid + 1, end);
int len1 = skyline1.size(), len2 = skyline2.size();
int i = 0, j = 0;
int height1 = 0, height2 = 0, prevHeight = 0;
while (i < len1 || j < len2) {
long x1 = i < len1 ? skyline1.get(i).get(0) : Long.MAX_VALUE;
long x2 = j < len2 ? skyline2.get(j).get(0) : Long.MAX_VALUE;
int x = 0;
if (x1 < x2) {
height1 = skyline1.get(i++).get(1);
x = (int)x1;
} else if (x1 > x2) {
height2 = skyline2.get(j++).get(1);
x = (int)x2;
} else {
height1 = skyline1.get(i++).get(1);
height2 = skyline2.get(j++).get(1);
x = (int)x1;
}
int currHeight = Math.max(height1, height2);
if (currHeight != prevHeight) {
List<Integer> point = new ArrayList<>();
point.add(x);
point.add(currHeight);
result.add(point);
}
prevHeight = currHeight;
}
return result;
}
}