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 中文
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值