【每天一道算法题】大楼轮廓问题

(可以自己先写 有哪里不懂可以私聊我 我们一起探讨)

题目:(本题需要用到有序表结构)

给定一个N×3的矩阵matrix,对于每一个长度为3的小数组arr,都表示一个大楼的三个数据。arr[0]表示大楼的左边界,arr[1]表示大楼的右边界,arr[2]表示大楼的高度(一定大于0)。每座大楼的地基都在X轴上,大楼之间可能会有重叠,请返回整体的轮廓线数组。

举例:

b640b8c20c454d179191aed898fc10ca.png

 代表的图像:

e8f4f657ca394c1e98b06a3fa8a12be9.png

返回的轮廓线数组如下 

afca98bce8bc434b8d78f1d26e6132ea.png

要求:

时间复杂度为O


(自己先理解,理解不了再看答案)

解答 (主要流程代码)

75f14a099b344f25b2c7d45e487d9bec.png

2851debec3284fe2872c8f13da80654f.png 

e3ef4ab5e2cd46beb4dc117c12585382.png 

思路如下:

 第一步:将所有的大楼数组变成描述高度变化的对象。
比如题目中的例子,matrix={

c5efe72c5e554f82935f65735e26fd90.png

 会变成描述高度变化的对象数组如下:

931d6bf20e9b4f369aec3dcf5dd8749a.png

第二步:将描述高度变化的对象数组排序,排序的比较策略如下。
1.第一个维度的值从小到大排序。
2.如果第一个维度的值相等,看第二个维度的值,“加入”排在前,“删除”排在后。
3.如果两个对象第一维度和第二个维度的值都相等,则认为两个对象相等,谁在前都行。
比如上一步的对象数组,排序之后的结果为:

a634e489b6ab4115aee4c1ea2535f9d9.png 

 第三步:按如下操作。
1)准备有序表 mapHeightT imes,key 是一个整数,代表高度,value 是这个高度目前出现的次数。当某个key出现的次数为0,则删掉这条记录。一开始mapHeight中没有任何记录。
2)准备有序表mapXvalueHeight,key是一个整数,代表X轴上的一个位置,value是这个位置上的最大高度。当某个 key 出现的次数为 0 时,删掉这条记录。一开始 mapXvalueHeight中没有任何记录。
第四步:根据第二步生成的描述高度变化的数组,对 mapHeightT imes和 mapXvalueHeight进行如下操作。
{1,加入,一个高度4},在mapHeightT imes中加入(4,1),表示高度4出现了1次(如果某个高度在mapHeightT imes中已经有记录,则只用把次数加1即可,在这一步关于高度4没有记录,所以新加入即可)。此时在x==1处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是4,将(1,4)记录在mapXvalueHeight中,表示在x==1处,最大高度是4。
此时,mapHeightT imes中所有的记录为:{4,1}。
此时,mapXvalueHeight中所有记录为:{1,4}。
{2,加入,一个高度6},在mapHeightT imes中加入(6,1),表示高度6出现了1次。此时在x==2处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是6,将(2,6)记录在mapXvalueHeight中,表示在x==2处,最大高度是6。
此时,mapHeightT imes中所有的记录为:{4,1},{6,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6}。
{3,加入,一个高度5},在mapHeightT imes中加入(5,1),表示高度5出现了1次。此时在x==3处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,依然是6,将(3,6)记录在mapXvalueHeight中,表示在x==3处,最大高度是6。
此时,mapHeightT imes中所有的记录为:{4,1},{6,1},{5,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6}。
{4,加入,一个高度7},在mapHeightT imes中加入(7,1),表示高度7出现了1次。此时在x==4处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是7,将(4,7)记录在mapXvalueHeight中,表示在x==4处,最大高度是7。
此时,mapHeightT imes中所有的记录为:{4,1},{6,1},{5,1},{7,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7}。
{5,删除,一个高度6},此时在mapHeightT imes中高度6只出现了1次,又是删除操作,所以彻底删掉key==6的记录(如果出现次数大于1次,则把次数减1即可,不需要彻底删除)。此时在x==5处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是7,将(5,7)记录在mapXvalueHeight中,表示在x==5处,最大高度是7。
此时,mapHeightT imes中所有的记录为:{4,1},{5,1},{7,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7}。
{6,删除,一个高度5},此时在mapHeightT imes中高度5只出现了1次,所以彻底删掉key==5的记录。此时在x==6处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是7,将(6,7)记录在mapXvalueHeight中

此时,mapHeightT imes中所有的记录为:{4,1},{7,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,7}。
{6,删除,一个高度7},此时在mapHeightT imes中高度7只出现了1次,所以彻底删掉key==7的记录。此时在x==6处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是4,将(6,4)记录在mapXvalueHeight中。
此时,mapHeightT imes中所有的记录为:{4,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4}。
{7,删除,一个高度4},此时在mapHeightT imes中高度4只出现了1次,所以彻底删掉key==4的记录。此时在 x==7 处,mapHeightTimes 已经空了,所以最大高度是 0,将(7,0)记录在mapXvalueHeight中。
此时,mapHeightT imes中所有的记录为:空。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4},{7,0}。
{9,加入,一个高度3},mapHeightT imes中加入(3,1),表示高度3出现了1次。此时在x==9处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是3,将(9,3)记录在mapXvalueHeight中,表示在x==9处,最大高度是3。
此时,mapHeightT imes中所有的记录为:{3,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4},{7,0},{9,3}。
{10,加入,一个高度5},mapHeightT imes中加入(5,1),表示高度5出现了1次。此时在x==10处,出现的所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是5,将(10,5)记录在mapXvalueHeight中,表示在x==10处,最大高度是5。
此时,mapHeightT imes中所有的记录为:{3,1},{5,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4},{7,0},{9,3},{10,5}。
{10,加入,一个高度2},mapHeightT imes中加入(2,1),表示高度2出现了1次。此时在x==10处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是5,将(10,5),记录在mapXvalueHeight中,表示在x==10处,最大高度是5。
此时,mapHeightT imes中所有的记录为:{3,1},{5,1},{2,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4},{7,0},{9,3},{10,5}。
{11,删除,一个高度3},此时在mapHeightT imes中高度3只出现了1次,所以彻底删掉key==3的记录。此时在x==11处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是5,将(11,5)记录在mapXvalueHeight中,表示在x==11处,最大高度是5。
此时,mapHeightT imes中所有的记录为:{5,1},{2,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4},{7,0},{9,3},{10,5},{11,5}。
{12,加入,一个高度4},在mapHeightT imes中加入(4,1),表示高度4出现了1次。此时在x==12处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是5,将(12,5),记录在mapXvalueHeight中,表示在x==12处,最大高度是5。
此时,mapHeightT imes中所有的记录为:{5,1},{2,1},{4,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4},{7,0},{9,3},{10,5},{11,5},{12,5}。
{12,删除,一个高度5},此时在mapHeightT imes中高度5只出现了1次,所以彻底删掉key==5的记录。此时在x==12处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是4,将(12,4),记录在mapXvalueHeight中,表示在x==12处,最大高度是4。

此时,mapHeightT imes中所有的记录为:{2,1},{4,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4},{7,0},{9,3},{10,5},{11,5},{12,4}。
{13,删除,一个高度2},此时在mapHeightT imes中高度2只出现了1次,所以彻底删掉key==2的记录。此时在x==13处,出现所有高度中的最大高度可以通过mapHeightT imes.lastKey得到,也就是4,将(13,4)记录在mapXvalueHeight中,表示在x==13处,最大高度是4。
此时,mapHeightT imes中所有的记录为:{4,1}。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4},{7,0},{9,3},{10,5},{11,5},{12,4},{13,4}。
{14,删除,一个高度4},此时在mapHeightT imes中高度4只出现了1次,所以彻底删掉key==4的记录。此时在 x==14 处,mapHeightT imes 已经为空,所以最大高度是 0,将(14,0)记录在mapXvalueHeight中,表示在x==14处,最大高度是0。
此时,mapHeightT imes中所有的记录为:空。
此时,mapXvalueHeight中所有的记录为:{1,4},{2,6},{3,6},{4,7},{5,7},{6,4},{7,0},{9,3},{10,5},{11,5},{12,4},{13,4},{14,0}。
第五步:根据第四步生成的mapXvalueHeight表,生成所有的轮廓线。mapXvalueHeight表其实统计了在X轴上出现的每个点在所有的操作都做完之后,得到的最大高度。轮廓线的产生其实只和每个点最终的最大高度变化有关。下面展示如何根据 mapXvalueHeight 表,生成轮廓线结果数组res。
{1,4},轮廓线开始产生,开始位置为1,高度为4,结束位置待定,目前的最大高度为4。res={{1,待定,4}}。
{2,6},之前的最大高度为4,现在最大高度变为6,所以之前结束位置待定的轮廓线,此时可以确定结束位置为2。同时新的轮廓线开始产生,开始位置为2,高度为6,结束位置待定,目前的最大高度为6。res={{1,2,4},{2,待定,6}}。
{3,6},之前的最大高度为6,现在最大高度仍是6,所以不产生任何信息。
{4,7},之前的最大高度为6,现在最大高度变为7,所以之前结束位置待定的轮廓线,此时可以确定结束位置为4。同时新的轮廓线开始产生,开始位置为4,高度为7,结束位置待定,目前的最大高度为7。res={{1,2,4},{2,4,6},{4,待定,7}}。
{5,7},之前的最大高度为7,现在最大高度仍是7,所以不产生任何信息。
{6,4},之前的最大高度为7,现在最大高度变为4,所以之前结束位置待定的轮廓线,此时可以确定结束位置为6。同时新的轮廓线开始产生,开始位置为6,高度为4,结束位置待定,目前的最大高度为4。res={{1,2,4},{2,4,6},{4,6,7},{6,待定,4}}。
{7,0},之前的最大高度为4,现在最大高度变为0,所以之前结束位置待定的轮廓线,此时可以确定结束位置为7。根据题目描述,大楼的高度一定大于0,如果某个位置的最大高度为0,一定没有高楼,所以没有新的轮廓线开始产生。res={{1,2,4},{2,4,6},{4,6,7},{6,7,4}}。
{9,3},轮廓线开始产生,开始位置为9,高度为3,结束位置待定,目前的最大高度为3。res={{1,2,4},{2,4,6},{4,6,7},{6,7,4},{9,待定,3}}。

10,5},之前的最大高度为 3,现在最大高度变为 5,所以之前结束位置待定的轮廓线,此时可以确定结束位置为10。同时新的轮廓线开始产生,开始位置为10,高度为5,结束位置待定,目前的最大高度为5。res={{1,2,4},{2,4,6},{4,6,7},{6,7,4},{9,10,3},{10,待定,5}}。
{11,5},之前的最大高度为5,现在最大高度仍是5,所以不产生任何信息。
{12,4},之前的最大高度为 5,现在最大高度变为 4,所以之前结束位置待定的轮廓线,此时可以确定结束位置为12。同时新的轮廓线开始产生,开始位置为12,高度为4,结束位置待定,目前的最大高度为4。res={{1,2,4},{2,4,6},{4,6,7},{6,7,4},{9,10,3},{10,12,5},{12,待定,4}}。
{13,4},之前的最大高度为4,现在最大高度仍是4,所以不产生任何信息。
{14,0},之前的最大高度为 4,现在最大高度变为 0,所以之前结束位置待定的轮廓线,此时可以确定结束位置为14。根据题目描述,大楼的高度一定大于0,如果某个位置的最大高度为0,一定没有高楼,所以没有新的轮廓线开始产生。res={{1,2,4},{2,4,6},{4,6,7},{6,7,4},{9,10,3},{10,12,5},{12,14,4}}。

最后返回res即可。。。。

 

 

 

  • 11
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值