LeeCode( 堆)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], …]
示例 1:
输入:buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
输出:[[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
解释:
图 A 显示输入的所有建筑物的位置和高度,
图 B 显示由这些建筑物形成的天际线。图 B 中的红点表示输出列表中的关键点。
示例 2:
输入:buildings = [[0,2,3],[2,5,3]]
输出:[[0,3],[5,0]]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/the-skyline-problem
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
- 先将所有的buildings 抽象成两个点(一个左上角 ,一个右上角)将他们放入points链表中,按x的值升序排列。
当x相同时有三种情况:
①当point1和point2简称(p1,p2)都是左上角点时,y1>y2,则高度大的p1放p2前面。
②当p1,p2都是左上角点时,y1<y2,则高度小的p1放p2前面。
③当p1是左上角点,p2是右上角点时,左上角点p1放在前面。
- 创建一个优先队列queue存放所有未遇到右上角点的建筑的高度,当遇到右上角点时将该点的高度从queue中删除,并且更新当前最高高度,判断是否发生变化,发生变化则将该点加入结果集res。
Java代码:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
public class 天际线 {
public List<List<Integer>> getSkyline(int[][] buildings) {
List<List<Integer>> points = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
int n = buildings.length;
for(int b[] : buildings){
List<Integer> p1 = new ArrayList<>();
p1.add(b[0]);
p1.add(-b[2]);
points.add(p1);
List<Integer> p2 = new ArrayList<>();
p2.add(b[1]);
p2.add(b[2]);
points.add(p2);
}
Collections.sort(points,new Comparator<List<Integer>>() {
@Override
public int compare(List<Integer> p1, List<Integer> p2) {
int x1 = p1.get(0);
int x2 = p2.get(0);
int y1 = p1.get(1);
int y2 = p2.get(1);
if(x1 != x2){
return x1 - x2;
}else{
return y1 - y2;
}
}
});
Queue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o2 - o1;
}
});
//放入起始高度
queue.offer(0);
int preMax = 0;
for(List<Integer> p : points){
int x = p.get(0);
int y = p.get(1);
//左上角
if(y<0){
queue.offer(-y);
}else{
//右上角
queue.remove(y);
}
//获取栈头元素,(因queue采用了降序排列,所以栈头元素为最大值)
int curMax = queue.peek();
//当前最大值出现变化
if(curMax != preMax){
List<Integer> temp = new ArrayList<>();
temp.add(x);
temp.add(curMax);
res.add(temp);
preMax = curMax;
}
}
return res;
}
}