Leetcode 0218: The Skyline Problem

题目描述:

A city’s skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Given the locations and heights of all the buildings, return the skyline formed by these buildings collectively.

The geometric information of each building is given in the array buildings where buildings[i] = [lefti, righti, heighti]:
1 left_i is the x coordinate of the left edge of the ith building.
2 right_i is the x coordinate of the right edge of the ith building.
3 height_i is the height of the ith building.

You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.
The skyline should be represented as a list of “key points” sorted by their x-coordinate in the form [[x1,y1],[x2,y2],…]. Each key point is the left endpoint of some horizontal segment in the skyline except the last point in the list, which always has a y-coordinate 0 and is used to mark the skyline’s termination where the rightmost building ends. Any ground between the leftmost and rightmost buildings should be part of the skyline’s contour.

Note: There must be no consecutive horizontal lines of equal height in the output skyline. For instance, […,[2 3],[4 5],[7 5],[11 5],[12 7],…] is not acceptable; the three lines of height 5 should be merged into one in the final output as such: […,[2 3],[4 5],[12 7],…]

中文描述:

城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回由这些建筑物形成的 天际线 。

每个建筑物的几何信息由数组 buildings 表示,其中三元组 buildings[i] = [lefti, righti, heighti] 表示:
1 left_i 是第 i 座建筑物左边缘的 x 坐标。
2 right_i 是第 i 座建筑物右边缘的 x 坐标。
3 height_i 是第 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], …]

Example 1:
在这里插入图片描述

Input: buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
Output: [[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
Explanation:
Figure A shows the buildings of the input.
Figure B shows the skyline formed by those buildings. The red points in figure B represent the key points in the output list.

扫描二维码关注公众号,回复: 12517425 查看本文章

Example 2:

Input: buildings = [[0,2,3],[2,5,3]]
Output: [[0,3],[5,0]]

Constraints:

1 <= buildings.length <= 104
0 <= left_i < right_i <= 231 - 1
1 <= height_i <= 231 - 1
buildings is sorted by lefti in non-decreasing order.

Time complexity: O(n2)
扫描线法:
将每个建筑看成在 x 轴两个竖线,左端表示开始并将高度计作负数,右端表示结束高度为正数。使用扫描线,初始化一个最大堆(堆顶为最大的高度),从左至右扫过,如果遇到左端点(高度为负数的端点),则入堆,如果遇到右端点(高度为正数的端点),则将其从堆中删除。使用 prev 变量记录上一个转折点,每次当堆顶的值不等于上一个转折点的值时,记录当前的端点和高度存入结果当中。
时间复杂度分析:遍历每个端点O(n), 在遍历的过程中每次都要加入到堆(PriorityQueue) 中,或者从堆中删除。对于Java PriorityQueue,找元素 O(n), 堆调整 heapify O(logn). 所以从堆中删除指定元素 花费 O(n)。 总共O(n2)。

class Solution {
    
    
    public List<List<Integer>> getSkyline(int[][] buildings) {
    
    
        List<List<Integer>> res = new ArrayList<>();
        List<int[]> height = new ArrayList<>();
        for(int[] b:buildings) {
    
    
            height.add(new int[]{
    
    b[0], -b[2]}); // left edge
            height.add(new int[]{
    
    b[1], b[2]}); // right edgs
        }
        Collections.sort(height, (a, b) -> {
    
    
            if(a[0] != b[0]) 
                return a[0] - b[0];
            return a[1] - b[1];
        });
        Queue<Integer> pq = new PriorityQueue<>((a, b) -> (b - a));
        pq.offer(0);
        int prev = 0;
        for(int[] h:height){
    
    
            if(h[1] < 0){
    
    
                // left edge
                pq.offer(-h[1]);
            }else{
    
    
                pq.remove(h[1]);
            }
            int cur = pq.peek();
            if(prev != cur) {
    
    
                res.add(Arrays.asList(h[0], cur));
                prev = cur;
            }
        }
        return res;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43946031/article/details/113831508