zoukankan      html  css  js  c++  java
  • sweep line-The Skyline Problem

    2020-01-10 17:51:05

    问题描述

    问题求解

    本题是经典的sweep line问题。

    对于sweep line问题我们需要考虑的只有两点:

    1. 延水平方向 / 时间方向 :时间队列 event queue,一般来说是一个优先队列;

    2. 延垂直方向sweep line status,即当前的扫描线的状态,一般会将交点按照顺序排序;

    对于本题来说,sweep line status可以使用一个multi set来进行维护,当然由于在Java中没有multi set,因此需要使用TreeMap来模拟。

    event queue的当然是使用优先队列,问题是如何进行排序,这个才是本题的核心难点。

    这里给出结论:

    大方向是按照x轴排序,如果x轴相等那么按照height排序;

    如果x轴相等,优先判断是否是左端点,如果是左端点,那么优先入队;

    如果同时是右端点,那么需要反序入队,就是height小的反而需要排在前面。

        public List<List<Integer>> getSkyline(int[][] buildings) {
            List<List<Integer>> res = new ArrayList<>();
            // 对于同x轴,优先将左端点入队列
            // 如果同是右端点,则要反序,小的先入队列
            // 其余按照正常的height顺序排列即可
            PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>(){
                public int compare(int[] o1, int[] o2) {
                    if (o1[0] == o2[0] && o1[2] != o2[2]) return o1[2] - o2[2];
                    if (o1[0] == o2[0] && o1[2] == 1 && o1[2] == o2[2]) return o1[1] - o2[1];
                    return o1[0] == o2[0] ? o2[1] - o1[1] : o1[0] - o2[0];
                }
            });
            TreeMap<Integer, Integer> map = new TreeMap<>();
            for (int[] b : buildings) {
                int s = b[0];
                int e = b[1];
                int h = b[2];
                pq.add(new int[]{s, h, 0});
                pq.add(new int[]{e, h, 1});
            }
            while(!pq.isEmpty()) {
                int[] event = pq.poll();
                int x = event[0];
                int h = event[1];
                int status = event[2];         
                int curr_max = map.size() == 0 ? 0 : map.lastKey();
                if (status == 0) {
                    if (h > curr_max) res.add(Arrays.asList(x, h));
                    map.put(h, map.getOrDefault(h, 0) + 1);
                }
                else {
                    map.put(h, map.get(h) - 1);
                    if (map.get(h) == 0) map.remove(h);
                    curr_max = map.size() == 0 ? 0 : map.lastKey();
                    if (h > curr_max) res.add(Arrays.asList(x, curr_max));
                }
                
            }
            return res;
        }
    

      

  • 相关阅读:
    关于阿里云centos 2.6下手机表情输入后无法保存到mysql数据库的问题调研及mysql版本从5.1升级到5.7的全过程纪要
    EXTJS 5 学习笔记2
    EXTJS 5 学习笔记1
    关于java.lang.String理解中的一些难点
    关于centos7中使用rpm方式安装mysql5.7版本后无法使用root登录的问题
    大数据专栏
    过采样中用到的SMOTE算法
    linux后台执行命令:&和nohup
    P,R,F1 等性能度量(二分类、多分类)
    word2vec模型cbow与skip-gram的比较
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/12177474.html
Copyright © 2011-2022 走看看