描述
水平面上有 N 座大楼,每座大楼都是矩阵的形状,可以用一个三元组表示 (start, end, height)
,分别代表其在x轴上的起点,终点和高度。大楼之间从远处看可能会重叠,求出 N 座大楼的外轮廓线。
外轮廓线的表示方法为若干三元组,每个三元组包含三个数字 (start, end, height),代表这段轮廓的起始位置,终止位置和高度。
请注意合并同样高度的相邻轮廓,不同的轮廓线在x轴上不能有重叠。
您在真实的面试中是否遇到过这个题? 是
样例
给出三座大楼:
[
[1, 3, 3],
[2, 4, 4],
[5, 6, 1]
]
外轮廓线为:
[
[1, 2, 3],
[2, 4, 4],
[5, 6, 1]
]
一开始没想明白怎么做,看题目像是矩形并集问题,一直在往线段树之类的方面想。后来看了别人的解题报告,发现是自己想偏了。
具体做法是把所有的线段的两个端点分别当成两个点保存起来,然后按x轴排序,保存时需要保存这个点是线段的起点还是终点。
接下来扫描所有点:若是起点,则往一个multiset当中插入一个当前线段的高,如果这个插入的高是目前set中的最大值,记录下left,如果不是最大值,不记录left,但是要往multiset插入当前的高。如果是终点,则在multiset中移除当前线段的高。此时观察被移除的高是否是multiset的最大值,如果不是最大值,证明当前的节点是被更高的楼覆盖了,如果是最大值,则说明当前的x就是right,保存left,right,height,存入答案数组。
大体的思路如上
然后就是这个题的各种细节很多,比如有重复点问题、当multiset为空时的处理。
重复点问题我的处理方案是非常小心的设计了排序函数,multiset为空时,有做特殊处理
具体看看代码吧,写的很冗长。
另:我看过别人的解题报告,有很多虽然思路一样但是质量很高很简洁的代码,值得学习
struct node{
int x;
int height;
bool is_begin;
};
bool node_cmp(node a,node b)
{
if(a.x==b.x)
{
if(a.is_begin&&b.is_begin)
return a.height>b.height;
else if(!a.is_begin&&!b.is_begin)
return a.height<b.height;
else
return a.is_begin;
}
else
return a.x<b.x;
}
class Solution {
public:
vector<vector<int>> buildingOutline(vector<vector<int>> &buildings)
{
int i;
vector<vector<int>>::const_iterator iter;
vector<node> node_list;
for(iter=buildings.cbegin();iter!=buildings.cend();++iter)
{
node temp;
temp.x=(*iter)[0];
temp.height=(*iter)[2];
temp.is_begin=true;
node_list.push_back(temp);
temp.x=(*iter)[1];
temp.height=(*iter)[2];
temp.is_begin=false;
node_list.push_back(temp);
}
sort(node_list.begin(),node_list.end(),node_cmp);
multiset<int,greater<int>> height_set;
vector<vector<int>> result;
int left,right;
for(i=0;i<node_list.size();++i)
{
node temp_node=node_list[i];
if(height_set.empty())
{
left=temp_node.x;
height_set.insert(temp_node.height);
}
else
{
if(temp_node.is_begin)
{
int origen_max=(*height_set.begin());
if(temp_node.height>origen_max)
{
height_set.insert(temp_node.height);
right=temp_node.x;
vector<int>temp;
temp.push_back(left);
temp.push_back(right);
temp.push_back(origen_max);
result.push_back(temp);
left=temp_node.x;
}
else
{
height_set.insert(temp_node.height);
}
}
else
{
int origen_max=(*height_set.begin());
multiset<int,less<int>>::iterator delete_iter=height_set.find(temp_node.height);
height_set.erase(delete_iter);
if(height_set.empty())
{
vector<int>temp;
right=temp_node.x;
temp.push_back(left);
temp.push_back(right);
temp.push_back(origen_max);
result.push_back(temp);
}
else if(origen_max!=(*height_set.begin()))
{
vector<int>temp;
right=temp_node.x;
temp.push_back(left);
temp.push_back(right);
temp.push_back(origen_max);
result.push_back(temp);
left=temp_node.x;
}
}
}
}
return result;
}
};