The Skyline Problem

水平面上有 N 座大楼,每座大楼都是矩阵的形状,可以用一个三元组表示 (start, end, height),分别代表其在x轴上的起点,终点和高度。大楼之间从远处看可能会重叠,求出 N 座大楼的外轮廓线。

外轮廓线的表示方法为若干三元组,每个三元组包含三个数字 (start, end, height),代表这段轮廓的起始位置,终止位置和高度。

Example

样例1

输入:
[
    [1, 3, 3],
    [2, 4, 4],
    [5, 6, 1]
]
输出:
[
    [1, 2, 3],
    [2, 4, 4],
    [5, 6, 1]
]

思路:扫描线算法;起飞的时候才加入一堆高度进行排序判断最高height,下降的时候,要remove 当前的高度,由于下降的点刚开始存的时候就是负数,所以remove的时候就是remove -负数。不参加评选了。还有注意点就是pq刚开始有可能是空的时候,curheight是0. 否则会报NPE;

class Solution {
    private class Node {
        public int x;
        public int height;
        public Node(int x, int height) {
            this.x = x;
            this.height = height;
        }
    }
    
    public List<List<Integer>> getSkyline(int[][] buildings) {
        List<List<Integer>> lists = new ArrayList<List<Integer>>();
        if(buildings == null || buildings.length == 0 || buildings[0].length == 0) {
            return lists;
        }
        
        List<Node> list = new ArrayList<>();
        for(int[] building: buildings) {
            list.add(new Node(building[0], building[2]));
            list.add(new Node(building[1], -building[2])); 
        }
        // 找高度最大的;
        Collections.sort(list, (a, b) -> (a.x != b.x ? a.x - b.x : b.height - a.height));
        
        int preheight = 0;
        int curheight = 0;
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>((a, b) -> (b - a));
        for(Node node: list) {
            if(node.height > 0) {
                //左边正数,加入pq进行排序;
                pq.offer(node.height);
            } else {
                // 因为存进去正负号是为了代表左边和右边,左边加入,右边remove,所以这里要remove -height;
                pq.remove(-node.height);
            }
            // 注意这里要判断pq是否为空,为空就是0,不为空才是peek;
            curheight = pq.isEmpty() ? 0 : pq.peek();
            if(curheight != preheight) {
                List<Integer> res = new ArrayList<>();
                res.add(node.x);
                res.add(curheight);
                lists.add(res);
                preheight = curheight;
            }
        }
        return lists;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值