LeetCode_The Skyline Problem

Posted rotk2015

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode_The Skyline Problem相关的知识,希望对你有一定的参考价值。

  1. 自己的一开始的想法将 x 轴抽象成一个数组,然后遍历一次建筑群,每遇到新一个建筑,就更新对应的子数组高度。最后将整个数组再遍历一次即可。这个思路很简单,但是存在一个问题,就是维护的数组长度,与建筑群的总占地宽度要求的输出精度相关,这样在极端条件下,可能会造成很大的空间浪费。同时,这种做法在最后遍历数组时,我们可以发现,有大量的重复数组值是无用的

  2. 后来看了下评论区和网上的资料,得到一个比较好的方案。

  3. 仔细观察可以发现:天际线的 key point 由建筑的边界构成。而建筑之间经常会有覆盖现象,如 [[2,9,10],[3,7,15]],这意味着在以建筑为单位处理时,我们要时不时的走回头路,更新之前已经赋值的高度。那么我们能否在扫描赋值时就盖棺定论,一次遍历即得到正确答案呢?

  4. 我们可将表示一个建筑的三元数组拆分成两个 <端点,高度> 的二元组,表示一个建筑的起点、终点。将所有建筑的二元组排序,然后遍历处理这些二元组即可。

  5. 代码如下:

    public List<List<Integer>> getSkyline(int[][] buildings) 
        List<List<Integer>> res = new ArrayList<>();
        List<int[]> points = new ArrayList<>();
        for(int[] b : buildings)
            points.add(new int[]b[0], -b[2]);
            // for the start node we use negative value.
            // 1. to distinguish between end and start node. 2. if there are two adjacent rectangles, the right start
            // node will be added to heap BEFORE we delete the left end node (because points is ASCENDING order
            // according to point[0] and point[1]). THEN, when we delete the end node, we can IMMEDIATELY UPDATE the
            // curMax to start node (if it's right), since we added start node IN ADVANCE.
            points.add(new int[]b[1], b[2]);
        
        Collections.sort(points, (a, b) -> 
            if(a[0]==b[0])
                return a[1]-b[1];
            else
                return a[0]-b[0];
        );
    
        TreeMap<Integer, Integer> map = new TreeMap<>();
        // k is height and v is total numbers.
        // TreeMap is ascending order according to the key value by default.
    
        int prevMax = 0;
        map.put(0,1);
        for(int[] p : points)
            //p[0] is x position and p[1] is height.
            if(p[1] < 0)
                map.put(-p[1], map.getOrDefault(-p[1], 0)+1);
                // put the start point and increase corresponding v.
            else
                if(map.get(p[1])>1)
                    map.put(p[1], map.get(p[1])-1);
                else
                    map.remove(p[1]);
            
    
            int curMax = map.lastKey();
            // get highest node of cur heap.
            if(curMax != prevMax)
                res.add(Arrays.asList(p[0], curMax));
                // x position is p[0] since curMax changed in this step.
                prevMax = curMax;
            
        
        return res;
    
    

参考资料:

  1. [LeetCode]218. The Skyline Problem 中文

以上是关于LeetCode_The Skyline Problem的主要内容,如果未能解决你的问题,请参考以下文章

OpenStack Skyline 现代化的管理界面

Skyline开发2-第一个程序

OpenStack新版UI管理skyline

OpenStack新版UI管理skyline

OpenStack新版UI管理skyline

skyline与cesium差异