资讯专栏INFORMATION COLUMN

[Leetcode] The Skyline Problem 天际线问题

hidogs / 2021人阅读

摘要:遍历时,通过一个堆来得知当前图形的最高位置。堆顶是所有顶点中最高的点,只要这个点没被移出堆,说明这个最高的矩形还没结束。对于左顶点,我们将其加入堆中。

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. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skyline formed by these buildings collectively (Figure B).


Buildings Skyline Contour The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left and right edge of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.

For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] .

The output is a list of "key points" (red dots in Figure B) in the format of [ [x1,y1], [x2, y2], [x3, y3], ... ] that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.

For instance, the skyline in Figure B should be represented as:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ].

Notes:

The number of buildings in any input list is guaranteed to be in the range [0, 10000]. The input list is already sorted in ascending order by the left x position Li. The output list must be sorted by the x position. 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], ...]

排序+堆 复杂度

时间 O(NlogN) 空间 O(N)

思路

如果按照一个矩形一个矩形来处理将会非常麻烦,我们可以把这些矩形拆成两个点,一个左上顶点,一个右上顶点。将所有顶点按照横坐标排序后,我们开始遍历这些点。遍历时,通过一个堆来得知当前图形的最高位置。堆顶是所有顶点中最高的点,只要这个点没被移出堆,说明这个最高的矩形还没结束。对于左顶点,我们将其加入堆中。对于右顶点,我们找出堆中其相应的左顶点,然后移出这个左顶点,同时也意味这这个矩形的结束。具体代码中,为了在排序后的顶点列表中区分左右顶点,左顶点的值是正数,而右顶点值则存的是负数。

注意

堆中先加入一个零点高度,帮助我们在只有最矮的建筑物时选择最低值

代码
public class Solution {
    public List getSkyline(int[][] buildings) {
        List result = new ArrayList<>();
        List height = new ArrayList<>();
        // 拆解矩形,构建顶点的列表
        for(int[] b:buildings) {
            // 左顶点存为负数
            height.add(new int[]{b[0], -b[2]});
            // 右顶点存为正数
            height.add(new int[]{b[1], b[2]});
        }
        // 根据横坐标对列表排序,相同横坐标的点纵坐标小的排在前面
        Collections.sort(height, new Comparator(){
            public int compare(int[] a, int[] b){
                if(a[0] != b[0]){
                    return a[0] - b[0];
                } else {
                    return a[1] - b[1];
                }
            }
        });
        // 构建堆,按照纵坐标来判断大小
        Queue pq = new PriorityQueue(11, new Comparator(){
            public int compare(Integer i1, Integer i2){
                return i2 - i1;
            }
        });
        // 将地平线值9先加入堆中
        pq.offer(0);
        // prev用于记录上次keypoint的高度
        int prev = 0;
        for(int[] h:height) {
            // 将左顶点加入堆中
            if(h[1] < 0) {
                pq.offer(-h[1]);
            } else {
            // 将右顶点对应的左顶点移去
                pq.remove(h[1]);
            }
            int cur = pq.peek();
            // 如果堆的新顶部和上个keypoint高度不一样,则加入一个新的keypoint
            if(prev != cur) {
                result.add(new int[]{h[0], cur});
                prev = cur;
            }
        }
        return result;
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64567.html

相关文章

  • LeetCode[218] The Skyline Problem

    摘要:复杂度思路利用的思想,先分成左右两部分,再进行。每次都要将的左上角和右下角推进,进行计算。观察左边和右边进行。 LeetCode[218] The Skyline Problem A citys skyline is the outer contour of the silhouette formed by all the buildings in that city when vie...

    keithyau 评论0 收藏0
  • [LintCode/LeetCode] Jump Game I & II

    摘要:建立动规数组,表示从起点处到达该点的可能性。循环结束后,数组对所有点作为终点的可能性都进行了赋值。和的不同在于找到最少的步数。此时的一定是满足条件的最小的,所以一定是最优解。 Jump Game Problem Given an array of non-negative integers, you are initially positioned at the first index...

    rose 评论0 收藏0
  • [LeetCode] Palindrome Number

    摘要:逐位看官,这两种解法一看便知,小子便不多费唇舌了。字符数组比较法原数翻转比较法 Problem Determine whether an integer is a palindrome. Do this without extra space. click to show spoilers. Some hints:Could negative integers be palindrom...

    刘厚水 评论0 收藏0
  • [LeetCode] 4Sum & 4Sum II

    摘要:和方法一样,多一个数,故多一层循环。完全一致,不再赘述, 4Sum Problem Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which ...

    sydMobile 评论0 收藏0
  • [LintCode/LeetCode] Sliding Window Maximum/Median

    摘要:窗口前进,删队首元素保证队列降序加入当前元素下标从开始,每一次循环都将队首元素加入结果数组 Sliding Window Maximum Problem Given an array of n integer with duplicate number, and a moving window(size k), move the window at each iteration fro...

    crelaber 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<