Leetcode 218. The Skyline Problem

原题描述很长,此处放链接:https://leetcode.com/problems/the-skyline-problem/description/

思路:
题目要求所有建筑行程的轮廓,并且给出高度变化的点即可。
暴力的做法,求出所有建筑的左右边界,遍历这个范围,在每个点上找出当前的最高值,如果与前一个最高值相同就跳过。

优化的解法是参考其他网上的解答,下面是自己做完后的思考。
上面的算法有两个问题:

  1. 有些点不需要查找高度,因为它不是有建筑物高度变化的地方。
  2. 在有建筑物高度变化的地方,遍历了所有建筑物,如果有一个数据结构能够直接求出当前的最大高度,那么时间复杂度就变小了,而这个数据结构就是堆。

第一步,我们用一个list来存储所有建筑物高度发生变化的点,要记录坐标和高度,然后先按坐标,再按高度排序,为了后续对堆的处理,这里需要规定建筑起点的高度记录为负数,终点记录为正数。

第二步,初始化一个最大堆(堆顶始终保持着当前堆内最大值),我们遍历上面的list,对每个元素,如果导致最大高度发生变化,那么这是一个轮廓改变点,需要加到结果集中。具体讲,对每个元素,如果是起点,需要把这个高度加入到堆内,把对之前做的负值再取负;如果是终点,证明这个建筑要在此消失了,需要把这个高度从堆内删除。做完上面的操作后,比较之前记录的轮廓高度与当前堆顶记录的最高高度,如果不同,就证明这个轮廓的高度发生变化了。

上面有一个操作是要从堆内删除元素,用JAVA的PriorityQueue,时间复杂度是O(n),这里可以用TreeMap或TreeSet进行优化。

public List getSkyline(int[][] buildings) {
    List res = new ArrayList<>();
    if (buildings == null || buildings.length == 0 || buildings[0].length == 0) {
        return res;
    }

    //init height list
    List Coors = new ArrayList<>();
    for (int[] building : buildings) {
        Coors.add(new int[]{building[0], -building[2]});
        Coors.add(new int[]{building[1], building[2]});
    }
    Collections.sort(Coors, new Comparator() {
        @Override
        public int compare(int[] o1, int[] o2) {
            if (o1[0] != o2[0]) {
                return o1[0] - o2[0];
            }
            return o1[1] - o2[1];
        }
    });

    //init PriorityQueue,  keep the max height until now
    Queue maxHeightHeap = new PriorityQueue<>(new Comparator(){
        public int compare(Integer a, Integer b) {
            return b - a;
        }
    });

    maxHeightHeap.add(0);
    int pre = 0, cur = 0;
    for (int i = 0; i < Coors.size(); i++) {
        int[] Coor = Coors.get(i);
        if (Coor[1] < 0) {
            maxHeightHeap.add(-Coor[1]);
        } else {
            maxHeightHeap.remove(Coor[1]);
        }
        cur = maxHeightHeap.peek();
        if (cur != pre) {
            res.add(new int[]{Coor[0], cur});
            pre = cur;
        }
    }

    return res;
}

你可能感兴趣的:(Leetcode 218. The Skyline Problem)