今天在leetcode上面看到一道题shyline 与这道题一模一样,但是leetcode比较专业把数据的范围给了出来,而lintcode没有,但是我发现其实lintcode的X轴是在300000以内的,所以就不需要一条边一条边的扫描了,直接扫描每个坐标就好了。这样就完全能过了。
class Solution {
public:
/**
* @param buildings: A list of lists of integers
* @return: Find the outline of those buildings
*/
vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
// write your code here
vector<vector<int> > res;
const int size = 300000;
int n = buildings.size();
if(n==0) return res;
sort(buildings.begin(),buildings.end());
priority_queue<vector<int>> hp;
int bp = 0,cur_h = -1,start = -1;
vector<int> build = buildings[bp];
for(int i=0;i<size;i++){
while(!hp.empty()){
if(hp.top()[2] < i ) hp.pop();//height overflow
else break;
}
if(!hp.empty()){
if(hp.top()[0] == cur_h) {
res.back()[1] = i;
}
else {
cur_h = hp.top()[0];
res.push_back({start,i,cur_h});
}
}
while(bp<n && build[0] == i) {
hp.push({build[2],build[0],build[1]});
if(++bp < n)
build = buildings[bp];
}
start = i;
}
return res;
}
};
这道题确实挺纠结的,在Lintcode上过的也挺奇葩,有时候能过,有时候又过不了,但总体而言还是过了,写一下记录一下思路
刚开始想的是用堆将大楼从高到低开始找轮廓,但是每次大楼分裂,或者从前面找到结果时,需要把vector里面的元素右移,复杂度太高,自然是过不了,只能过到第17组数据
后来就改成了按坐标从左至右扫描大楼边的方式,并通过大堆记录当前楼的最高值,依次找出大楼轮廓。
将大楼的边按照进楼和出楼的方式存储,然后按照X坐标大小从小到大排列,并开始从左至右扫描edges,当遇到边edge是进楼时,则往堆中插入该栋大楼,
并扫描将堆顶元素中无效元素进行删除(该楼的右侧小于当前edge), 然后依次找到上次的edge与当前edge以及当前最大高度的大楼轮廓,如果上次的高度与本次高度一致则只需要延续上个edge的右侧。
struct HightCmp{
bool operator()(vector<int> a,vector<int> b){
return a[2]<b[2];
}
};
class Solution {
public:
/**
* @param buildings: A list of lists of integers
* @return: Find the outline of those buildings
*/
vector<vector<int> > buildingOutline(vector<vector<int> > &buildings) {
// write your code here
vector<vector<int> > res;
if(buildings.size()==0) return res;
vector<vector<int>> edges;
vector<int> edge(4,0);
for(vector<int> bd : buildings){//n
edge[0] = bd[0];edge[1] = bd[1];
edge[2] = bd[2];edge[3] = 1;
edges.push_back(edge);
edge[0] = bd[1];edge[3] = 0;
edges.push_back(edge);
}
sort(edges.begin(), edges.end());//n
priority_queue<vector<int>,vector<vector<int>>,HightCmp> q;
vector<int> bd(3,0),tb;
int last = -1;
for(vector<int> edg : edges){//n
while(!q.empty()){//building unavailable logn
if(edg[0] > q.top()[1]) q.pop();
else break;
}
if(q.empty() || last == edg[0]){
if(edg[3]){
bd = {edg[0],edg[1],edg[2]};
q.push(bd);
}
last = edg[0];
continue;
}
tb = q.top();
if(res.empty() || res.back()[2] != tb[2]){
bd = {last,edg[0],tb[2]};
res.push_back(bd);
}else{
res.back()[1] = edg[0];
}
if(edg[3]){
bd = {edg[0],edg[1],edg[2]};
if(bd[1] > tb[1] || tb[2] < bd[2])q.push(bd);
}
last = edg[0];
}
return res;
}
};