218. 天际线问题
城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回由这些建筑物形成的 天际线 。
每个建筑物的几何信息由数组 buildings 表示,其中三元组 buildings[i] = [lefti, righti, heighti] 表示:
lefti 是第 i 座建筑物左边缘的 x 坐标。
righti 是第 i 座建筑物右边缘的 x 坐标。
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], ...]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/the-skyline-problem
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
有序表
import java.util.*;
class Solution {
public List<List<Integer>> getSkyline(int[][] buildings) {
if (buildings == null || buildings.length == 0 || buildings[0].length == 0) {
return Collections.emptyList();
}
Operation[] operations = new Operation[buildings.length * 2];
for (int i = 0; i < buildings.length; ++i) {
operations[i * 2] = new Operation(buildings[i][0], buildings[i][2]);
operations[i * 2 + 1] = new Operation(buildings[i][1], -buildings[i][2]);
}
Arrays.sort(operations, new Comparator<Operation>() {
@Override
public int compare(Operation o1, Operation o2) {
if (o1.coordinate == o2.coordinate) {
return Integer.compare(o2.change, o1.change);
} else {
return Integer.compare(o1.coordinate, o2.coordinate);
}
}
});
List<List<Integer>> ret = new ArrayList<>();
int preHeight = 0;
TreeMap<Integer, Integer> heightTimesMap = new TreeMap<>();
for (int i = 0; i < operations.length; ++i) {
Integer times = heightTimesMap.getOrDefault(Math.abs(operations[i].change), 0);
if (operations[i].change >= 0) {
heightTimesMap.put(operations[i].change, times + 1);
} else {
if (times == 1) {
heightTimesMap.remove(-operations[i].change);
} else {
heightTimesMap.put(-operations[i].change, times - 1);
}
}
int curMaxHeight = heightTimesMap.isEmpty() ? 0 : heightTimesMap.lastKey();
if (curMaxHeight != preHeight) {
ret.add(Arrays.asList(operations[i].coordinate, curMaxHeight));
preHeight = curMaxHeight;
}
}
return ret;
}
}
class Operation {
int coordinate;
int change;
public Operation(int coordinate, int change) {
this.coordinate = coordinate;
this.change = change;
}
}
优先队列
import java.util.*;
class Solution {
public List<List<Integer>> getSkyline(int[][] buildings) {
PriorityQueue<Coordinate> queue = new PriorityQueue<>(new Comparator<Coordinate>() {
@Override
public int compare(Coordinate o1, Coordinate o2) {
return Integer.compare(o2.height, o1.height);
}
});
List<Integer> boundaries = new ArrayList<>(buildings.length * 2);
for (int[] building : buildings) {
boundaries.add(building[0]);
boundaries.add(building[1]);
}
Collections.sort(boundaries);
List<List<Integer>> ret = new ArrayList<>();
int preHeight = 0;
int n = buildings.length, idx = 0;
for (int boundary : boundaries) {
while (idx < n && buildings[idx][0] <= boundary) {
queue.offer(new Coordinate(buildings[idx][1], buildings[idx][2]));
idx++;
}
while (!queue.isEmpty() && queue.peek().x <= boundary) {
queue.poll();
}
int curMaxHeight = queue.isEmpty() ? 0 : queue.peek().height;
if (curMaxHeight != preHeight) {
ret.add(Arrays.asList(boundary, curMaxHeight));
preHeight = curMaxHeight;
}
}
return ret;
}
}
class Coordinate {
int x;
int height;
public Coordinate(int x, int height) {
this.x = x;
this.height = height;
}
}
心之所向,素履以往 生如逆旅,一苇以航

浙公网安备 33010602011771号