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;
    }
}
相关文章
|
机器学习/深度学习
智能体DS-Agent基于案例推理,让GPT-4数据科学任务接近100%
【4月更文挑战第20天】DS-Agent是结合案例推理(CBR)和大型语言模型的新研究,旨在提升自动化数据科学任务效率。通过自动迭代管道,它能理解任务、构建模型并优化性能。在开发阶段,成功率高达100%,部署阶段平均提高36%的一次通过率,降低成本,使开源LLMs也能高效处理数据科学任务。然而,LLMs的生成问题和资源限制仍是挑战。论文链接:https://arxiv.org/pdf/2402.17453.pdf
366 4
|
3月前
|
iOS开发
ios虚拟摄像头插件,iPhone苹果替换相机软件,通过xposed框架实现
本项目包含三部分内容:1) 通过MobileSubstrate Hook系统相机进程,替换原始视频流数据的核心代码;2) 基于SwiftUI设计的多功能摄像头界面,支持摄像头切换、滤镜选择和视频源配置;3) 使用PHPickerViewController实现本地视频选择、时长滑块控制及视频裁剪导出功能。适用于学习iOS底层Hook技术与现代UI开发结合的应用场景。下载地址:https://www.pan38.com/share.php?code=BCjmZ,提取码:8888(仅供学习参考)。
|
12月前
|
机器学习/深度学习 数据采集
详解Diffusion扩散模型:理论、架构与实现
【9月更文挑战第23天】扩散模型(Diffusion Models)是一类基于随机过程的深度学习模型,通过逐步加噪和去噪实现图像生成,在此领域表现优异。模型分正向扩散和反向生成两阶段:前者从真实数据加入噪声至完全噪音,后者则学习从噪声中恢复数据,经由反向过程逐步还原生成清晰图像。其主要架构采用U-net神经网络,实现过程中需数据预处理及高斯噪声添加等步骤,最终通过模型逆向扩散生成新数据,具有广泛应用前景。
707 0
|
机器学习/深度学习 人工智能 自然语言处理
耳朵没错,是声音太真了,字节豆包语音合成成果Seed-TTS技术揭秘
【7月更文挑战第5天】字节跳动的Seed-TTS技术在语音合成领域实现重大突破,生成的语音与真人难辨真假。基于深度学习的模型能模拟多种情感、口音,适用于智能客服、有声读物等场景。尽管面临计算资源需求大、个别情况合成质量不稳及潜在伦理问题,该技术仍标志着语音合成的新高度。[论文链接](https://arxiv.org/abs/2406.02430)**
726 1
|
存储 人工智能 API
阿里云百炼应用实践系列-10分钟在企业微信中集成一个 AI 助手
在阿里云平台上,您只需十分钟,无需任何编码,即可在企业微信上为您的组织集成一个具备大模型能力的AI助手。此助手可24小时响应用户咨询,解答各类问题,尤其擅长处理私域问题,从而成为您企业的专属助手,有效提升用户体验及业务竞争力。
1172 4
|
消息中间件 监控 Cloud Native
阿里云云原生微服务高级工程师认证(ACP级-Alibaba Cloud Certification Professional)考试大纲
介绍阿里云云原生微服务高级工程师认证(ACP级-Alibaba Cloud Certification Professional)所需具备的知识及学习方法等。
958 1
|
存储 前端开发 区块链
常见的 EVM 版本以及它们的区别
常见的 EVM 版本以及它们的区别
241 5
|
人工智能 安全 云计算
阿里云服务器购买之后发票如何申请?申请发票流程及常见问题参考
申请发票是很多用户尤其是企业级用户在购买完阿里云服务器之后非常关注的问题,对于初次购买阿里云服务器的用户来说,往往并不清楚如何找阿里云申请发票,本文以图文形式为大家介绍阿里云服务器购买完成之后申请发票的详细流程以及常见问题。
阿里云服务器购买之后发票如何申请?申请发票流程及常见问题参考
|
设计模式 测试技术 C#
WPF/C#:在WPF中如何实现依赖注入
WPF/C#:在WPF中如何实现依赖注入
334 0
|
数据采集 JSON 测试技术
抖音视频爬取项目:Dusk库的使用示例
抖音视频爬取项目:Dusk库的使用示例