zoukankan      html  css  js  c++  java
  • [LeetCode-JAVA] The Skyline Problem

    题目:题目太长了,见链接-- > The Skyline Problem 

    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], ...]

    题意:记录每一次建筑的拐点,连续的相同高度,只记录最前面的。

    思路:将每一个竖线按顺序存入,对于每一个矩形,都有高度相同的两条竖线,为了在一次扫描的时候,能将所有的竖线都加入,利用一个小技巧,将右边界的高度存为负值,恰好可以对其标记。将存入的list排序,需要自定义一个比较器比较a[],b[],如果a[0] == b[0] 说明竖线重合,这个时候应该是高的在前面,如果a[0] != b[0] 只需按照a[0]b[0]从小到大即可。

    最后在遍历list的时候,为了满足note4,即连续相同的高度只记录最前即可,因此需要用到pre和cur分别记录当前的最高和上一次的最高。在判断的时候,需要维护每次当前的最大值,可以用PriorityQueue权重队列,其构造原理是大顶堆,即根节点为最小(或最大)的二叉树,默认跟为最小值,根据题意,本题需要自己定义一个比较器,根保存当前最大值(可以注意我下面说的堆个队里,是同一个概念,为了方便理解,不同的时候用了不同的说法)。

    最核心的思想:扫描到左边界的时候,将高度加入到大顶堆,cur的值去peek即为当前的最大值,当cur和pre不同的时候,将坐标加入结果队列即可,当为右边界时(高度为负值),证明该矩形已经到头,在堆中去掉其高度值,如果此时队列为空,则证明此处非连续,即此时应加入的高度为0,如果不为空,则更新相应当前最高即可。

    代码:

    public class Solution {
        //大顶推比较器
        public class MaxCom implements Comparator<Integer> {
            public int compare(Integer a, Integer b){
                return b - a ; // 大的在堆的顶端
            }
        } 
        //数组比较器
        public class ArrayCom implements Comparator<int[]> {
            public int compare(int[] a, int[] b) {
                if(a[0] != b[0]) return a[0] - b[0];  //先按左边界进行排序
                return b[1] - a[1];  // 相等 则高的在前面
            }
        }
        public List<int[]> getSkyline(int[][] buildings) {  
            List<int[]> res = new ArrayList<int[]>();  
            PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11, new MaxCom());
            
            List<int[]> ver = new ArrayList<int[]>();  // 记录每一个竖线
            for(int i = 0 ; i < buildings.length ; i++){
                int[] temp = buildings[i]; 
                ver.add(new int[]{temp[0], temp[2]});  // 左边界竖线
                ver.add(new int[]{temp[1], -temp[2]});  // 右边界竖线 为了区分 存入负值
            }
            Collections.sort(ver, new ArrayCom());
            
            int cur = 0, pre = 0;
            for(int i = 0 ; i < ver.size() ; i++){
                int[] temp = ver.get(i);
                if(temp[1] > 0) {  // 左边界
                    maxHeap.offer(temp[1]);  //高度入队
                    cur = maxHeap.peek(); // 当前最高的
                }else { // 右边界
                    maxHeap.remove(-temp[1]);  // 将对应的高度从堆中删除 这里就是右边存负值的方便之处
                    cur = (maxHeap.peek() == null ? 0 : maxHeap.peek()); // 如果右边界是最后一个则高度为0,否则更新当前最高
                }
                if(cur != pre) {  // 与上一个最高的不相等
                    res.add(new int[]{temp[0], cur});
                    pre = cur;  // 保存当前高度为下一次的前面高度
                }
            }
            return res;       
        }
    }

     参考链接:http://blog.csdn.net/xudli/article/details/46349383

  • 相关阅读:
    Cannot attach the file *.mdf as database
    frameset frame 实例和用法 转
    remove element
    伸展树--java
    Remove Duplicates from Sorted Array
    merge two sorted lists
    valid parentheses
    Longest Common Prefix
    palindrome number(回文数)
    Two Sum
  • 原文地址:https://www.cnblogs.com/TinyBobo/p/4592061.html
Copyright © 2011-2022 走看看