• leetcode-218.天际线问题



    题目详情

    题目

    简单的概括一下题目:给定建筑物的起止位置和高度,返回建筑物轮廓(天际线)的拐点。


    示例1:

    示例

    输入:buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
    输出:[[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
    解释:
    图 A 显示输入的所有建筑物的位置和高度,
    图 B 显示由这些建筑物形成的天际线。图 B 中的红点表示输出列表中的关键点。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    示例2:

    输入:buildings = [[0,2,3],[2,5,3]]
    输出:[[0,3],[5,0]]
    
    • 1
    • 2

    首先,这道题要求我们寻找一些关键点,这些关键点一定位于高度变化的地方
    所以我们需要用一个数据结构记录从左到右扫过的高度的变化情况,要实现:
    1.当我们遇到一个大楼的左端点时,将这个大楼的高度加入记录
    2.当我们遇到一个大楼的右端点时,将这个大楼的高度删除记录
    要想实现2,必须要能查找到对应的高度进行删除
    set只能存储一些互不相同的元素,而这道题可能会产生相同高度的情况
    所以我们就利用允许有相同元素的multiset数据结构

    详细代码及解释:

    class Solution 
    {
    public:
        vector<vector<int>> getSkyline(vector<vector<int>>& buildings) 
        {
            vector<vector<int>> res;
            vector<pair<int, int>> height;
            for (auto &b : buildings)//记录每个建筑的左右端点,高度
            {
            /*
            b[0],b[1]是建筑左、右端点 b[2]是建筑的高度
            但是为什么记录高度b[2]时要一个负一个正呢?
            因为我们下面有一个sort操作,而sort会从小到大排序
            height从小到大排序,b[0],b[1]这些端点可能会存在重合情况
            当左端点重合时,我们要的是最高点,因为此时总天际线是拔高的
            当右端点重合时,我们要的是最低点,因为此时总天际线是降低的
            只要我们将左端点对应的高度设置为相反数,那么sort将会实现:
            左端点重合就按照高度从高到低排序,右端点重合就按照从低到高排序
            */  
                height.push_back({b[0], -b[2]});
                height.push_back({b[1], b[2]});
            }
            sort(height.begin(), height.end()); //排序后遍历的将是一个个端点而不是一个个建筑
    
            multiset<int> st;
            st.insert(0);   //我们最终天际线肯定是归为平地0的,这里需要初始化一下
            //之前的最大高度       当前的最大高度
            int preMaxHeight = 0, curMaxHeight = 0;
            for (auto &h : height) //遍历排好序的端点
            {
                //h.second<0说明是某个左端点(有重合情况的时候这里就会是较高的)
                if (h.second < 0) //"可能"需要拔高天际线了("可能"的原因:可能不高于当前最高建筑)
                {
                    st.insert(-h.second); //高度取回正数入队(入队后自动由高到低排序好了)
                }
                else      //右端点 "可能"需要降低天际线了("可能"的原因:可能不是当前最高建筑的右端点)
                {
                    st.erase(st.find(h.second));//当前右端点对应的高度出队(对应建筑结束了)
                }
    
                curMaxHeight = *st.rbegin();//临时存储当前的最大高度
    
                if (curMaxHeight != preMaxHeight) //最大高度变化了,就需要存入这个关键点了
                {
                    res.push_back({h.first, curMaxHeight});//存入当前关键点
                    preMaxHeight = curMaxHeight;          //当前最高赋予上一次最高
                }
            }
            return res;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
  • 相关阅读:
    Android开发之指南针
    集群配置步骤_java培训
    介绍BootLoader、PM、kernel和系统开机的总体流程
    树莓派的常用系统配置
    git 配置
    【SQL server速成之路】——身份验证及建立和管理用户账户
    安装GPT 学术优化 (GPT Academic)@FreeBSD
    Java的NIO体系
    【刷题笔记9.25】LeetCode:相交链表
    全链路压测的整体架构设计,以及5种实现方案流量染色方案、数据隔离方案、接口隔离方案、零侵入方案、服务监控方案【代码级别】
  • 原文地址:https://blog.csdn.net/Gundam103/article/details/126247553