218. 天际线问题

简介: 218. 天际线问题

前言

城市的 天际线 是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回 由这些建筑物形成的 天际线 。

每个建筑物的几何信息由数组 buildings 表示,其中三元组 buildings[i] = [lefti, righti, heighti] 表示:

lefti 是第 i 座建筑物左边缘的 x 坐标。
righti 是第 i 座建筑物右边缘的 x 坐标。
heighti 是第 i 座建筑物的高度。
你可以假设所有的建筑都是完美的长方形,在高度为 0 的绝对平坦的表面上。

天际线 应该表示为由 “关键点” 组成的列表,格式 [[x1,y1],[x2,y2],...] ,并按 x 坐标 进行 排序 。关键点是水平线段的左端点。列表中最后一个点是最右侧建筑物的终点,y 坐标始终为 0 ,仅用于标记天际线的终点。此外,任何两个相邻建筑物之间的地面都应被视为天际线轮廓的一部分。

注意:输出天际线中不得有连续的相同高度的水平线。例如 [...[2 3], [4 5], [7 5], [11 5], [12 7]...] 是不正确的答案;三条高度为 5 的线应该在最终输出中合并为一个:[...[2 3], [4 5], [12 7], ...]

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/the-skyline-problem
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

一、解题思路

轮廊线怎么去找?
轮廓线的产生只来自于最大高度的变化。

二、解题步骤

怎么追踪最大高度
首先我们要定义一种对象Node
Node里面记录这每一个点的位置X
高度是否上升isAdd 上升为true,下降为false
生成对象数组,每一个数组元素对应两个对象,分别为加高度和减高度
对象安装下标来排序

    public class NodeComparator implements Comparator<Node>{
        public int compare(Node o1,Node o2){
            return o1.x-o2.x;
        }
    }
    public List<List<Integer>> getSkyline(int[][] buildings) {
        int n=buildings.length;
        Node[] nodes=new Node[n*2];
        for(int i=0;i<n;i++){
            nodes[i*2]=new Node(buildings[i][0],true,buildings[i][2]);
            nodes[i*2+1]=new Node(buildings[i][1],false,buildings[i][2]);
        }
        Arrays.sort(nodes,new NodeComparator());

准备一个有序表map
key代表高度,按照有序组织, value代表这个高度加入的次数
加入之后,有序表中拿出最大的key, logN复杂度,我就可以知道最大高度的变化
1位置加了高度4,次数变成2,最大高度没有变化,还是4
2位置加了高度5,次数1,我就知道在2位置最大高度由4变成了5
点的高度h

image.png

6位置减一个高度5,减成了0,记录删掉,我就知道此时最大高度由5回到了4
7位置减一个4,只减了一次,最大高度没有变化
8位置又减了一个4,次数0,整条记录干掉,最大高度回到0
为什么我要把高度设计成次数的,因为有可能有多个高度并存,而我删只能删一次

总结

如果有N个大楼导出2N个对象,因为一个大楼有在某个时刻加一个高度,在某个时刻减一个高度,这2N个对象只根据第一维数据排序。在同一个位置做加加减减。你就会知道X轴每一个你需要关心的点,它最大高度最终变成了啥,以最后一次为准。你有了这么一个过程,你生成轮廊线是就搞定了。

import java.util.Map.Entry;
class Solution {
    public class Node{
        public int x;
        public boolean isAdd;
        public int h;
        public Node(int x,boolean isAdd,int h){
            this.x=x;
            this.isAdd=isAdd;
            this.h=h;
        }
    }
    public class NodeComparator implements Comparator<Node>{
        public int compare(Node o1,Node o2){
            return o1.x-o2.x;
        }
    }
    public List<List<Integer>> getSkyline(int[][] buildings) {
        int n=buildings.length;
        Node[] nodes=new Node[n*2];
        for(int i=0;i<n;i++){
            nodes[i*2]=new Node(buildings[i][0],true,buildings[i][2]);
            nodes[i*2+1]=new Node(buildings[i][1],false,buildings[i][2]);
        }
        Arrays.sort(nodes,new NodeComparator());
        TreeMap<Integer,Integer> mapHeightTime=new TreeMap<>();
        TreeMap<Integer,Integer> mapXHeight=new TreeMap<>();
        for(int i=0;i<nodes.length;i++){
            if(nodes[i].isAdd){
                if(!mapHeightTime.containsKey(nodes[i].h)){
                    mapHeightTime.put(nodes[i].h,1);
                }else{
                    mapHeightTime.put(nodes[i].h,mapHeightTime.get(nodes[i].h)+1);
                }
            }else{
                if(mapHeightTime.get(nodes[i].h)==1){
                    mapHeightTime.remove(nodes[i].h);
                }else{
                    mapHeightTime.put(nodes[i].h,mapHeightTime.get(nodes[i].h)-1);
                }
            }
            if(mapHeightTime.isEmpty()){
                mapXHeight.put(nodes[i].x,0);
            }else{
                mapXHeight.put(nodes[i].x,mapHeightTime.lastKey());
            }
        }
        

        List<List<Integer>> ans = new ArrayList<>();
        for (Entry<Integer, Integer> entry : mapXHeight.entrySet()) {
            int curX = entry.getKey();
            int curMaxHeight = entry.getValue();
            if (ans.isEmpty() || ans.get(ans.size() - 1).get(1) != curMaxHeight) {
                ans.add(new ArrayList<>(Arrays.asList(curX, curMaxHeight)));
            }
        }
        return ans;
    }
}
相关文章
|
2月前
|
机器人 Python
集能量宝石
集能量宝石
18 2
|
2月前
leetcode-807:保持城市天际线
leetcode-807:保持城市天际线
21 0
|
9月前
|
算法 测试技术 C++
C++算法:城市天际线问题
C++算法:城市天际线问题
[蓝桥杯 2018 省 B] 螺旋折线
[蓝桥杯 2018 省 B] 螺旋折线
40 0
|
传感器 人工智能 边缘计算
人形机器人火了,距离我们还有多远?
随着“擎天柱”的推出,让人形机器人这一新兴赛道引起市场的广泛关注,这是否就意味着人形机器人商业化的开启呢?
133 0
人形机器人火了,距离我们还有多远?
坚持写算法题的第四周(四)
坚持写算法题的第四周(四)
坚持写算法题的第四周(四)
坚持写算法题的第四周(五)
坚持写算法题的第四周(五)
坚持写算法题的第四周(五)