ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LEETCODE——每日一题

2021-07-13 21:32:42  阅读:313  来源: 互联网

标签:buildings 12 天际线 队列 每日 boundaries que LEETCODE


Leecode218:天际线问题

题目链接 [2021_07_13]
联想到的题型:方法——优先队列进行优化求解
会议室II

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

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

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

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

示例 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 中的红点表示输出列表中的关键点。
示例 2:

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

提示:

1 <= buildings.length <= 104
0 <= lefti < righti <= 231 - 1
1 <= heighti <= 231 - 1
buildings 按 lefti 非递减排序

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

思路:
暴力法:
使用O(n)地枚举建筑的每个边缘作为关键点的横坐标,过程中我们 O(n)O(n) 地检查每一座建筑是否「包含该横坐标」,找到最大高度,即为该关键点的纵坐标。该算法的时间复杂度是 O(n*n)
优化: 使用优先队列来优化寻找最大高度的时间,在从左到右枚举横坐标的过程中,实时的更新优先队列。这样无论如何,优先队列的队首元素即为最大高度。为了维护优先队列,我们应该使用 延时删除 的技巧。无需每次横坐标改变就立刻将优先队列中所有不符合条件的元素都删除,而只需要保证优先队列的队首元素「包含该横坐标」即可。
**注意特殊情况下:**在部分情况下,当横坐标为右边缘时,对于唯一的建筑对其纵坐标没有贡献。因此该横坐标对应的纵坐标的大小为0。

/*
时间复杂度:O(nlogn),其中n为建筑数量。每座建筑至多需要入队出队一次,单次时间复杂度为O(nlogn)
空间复杂度:O(n),其中n为建筑数量,数组boundaries和优先队列的空间占用均为O(n)
*/
class Solution {
public:
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
        //区间内取最大的问题,有点类似那个会议室
        //10 15 15  12 0 10 8 0
        //[0,10][3,15][7,12][12,0][15,10][20,8][24,0]
        //lambada表达式,是优先队列以结束点从小到大排列;优先队列que
        auto cmp = [](const pair<int, int>& a, const pair<int, int>& b)->bool{return a.second < b.second;};
        //decltype推出匿名类的类型
        priority_queue<pair<int, int>, vector<pair<int,int>>, decltype(cmp)> que(cmp);
        //将所有边界点放入boundaries中
        vector<int> boundaries;
        for(auto& building : buildings)
        {
            boundaries.emplace_back(building[0]);
            boundaries.emplace_back(building[1]);
        }
        //默认以第一位数字进行从小到大的排序
        sort(boundaries.begin(), boundaries.end());

        vector<vector<int>> ret;
        int n = buildings.size(), idx = 0;
        //遍历每个端点
        for(auto& boundary : boundaries)
        {
            while(idx < n && buildings[idx][0] <= boundary)
            {
                que.emplace(buildings[idx][1] , buildings[idx][2]);
                idx++;
            }
            //如果端点已经出了队列中的端点了,就将该端点直接移除
            while(!que.empty() && que.top().first <= boundary){
                que.pop();
            }
            int maxn = que.empty() ? 0 : que.top().second;
            //如果ret原始为空,或者当前的最大值不等于上一个的最大值,也就是maxn不作为上一个的延长线,
            if(ret.size() == 0 || maxn != ret.back()[1])
            {
                ret.push_back({boundary, maxn});
            }
        }   
        return ret;
    }
};

标签:buildings,12,天际线,队列,每日,boundaries,que,LEETCODE
来源: https://blog.csdn.net/baidu_40686549/article/details/118711069

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有