题目来源 点击打开链接
这道题经过好多次修改,,最主要是时间复杂度问题。
下面讲讲思路:
第一个重要转化是将所有矩形转变为向上跳变和向下跳变两种情况。之后对所有的上跳变和下跳变排序。用vector。
需要另一个容器用来维护当前的高度。当前重叠高度height必须是一个可检索的存储方式。
height一开始使用vector 但是涉及到非常多的插入和删除操作,所以改为链表,而且使用不删除的形式,链表中每个节点使用一个count来实现该高度是否存在。
bool operator< (const Rect_fun &a) const
这个逻辑很重要,对于建立好的上下跳变的vector,首先根据x进行排序(x小的排在前面),其次对于相同的x,根据flag排序,flag==1向上跳变排在前面,最后对于相同x相同flag,向上跳变的高度排在前面,向下跳变的高度排在后面。
struct HeightNode
{
int h;
int count;
HeightNode *next;
HeightNode(int hh, int cc): h(hh), count(cc), next(NULL){}
};
int findHeightMax(HeightNode *ptr)
{
int max = 0;
while(ptr != NULL)
{
if(ptr->h > max && ptr->count > 0)
max = ptr->h;
ptr = ptr->next;
}
return max;
}
int getHeightSize(HeightNode *ptr)//可优化
{
int count=0;
while(ptr != NULL)
{
count += ptr->count;
ptr = ptr->next;
}
return count;
}
void deleteHeight(HeightNode *ptr, int ii)
{
while(ptr != NULL)
{
if(ptr->h == ii)
{
ptr->count--;
}
ptr = ptr->next;
}
}
void addHeight(HeightNode *ptr, int ii)
{
while(1)
{
if(ptr->h == ii)
{
ptr->count++;
return ;
}
if(ptr->next != NULL)
ptr = ptr->next;
else
break;
}
//如果没找到
HeightNode *p = new HeightNode(ii,1);
ptr->next = p;
}
struct Rect_fun
{
int x;
bool flag;//1是向上跳变 0是向下跳变
int height;
Rect_fun(int xx, int f, int h) : x(xx), flag(f), height(h){}
//对于向量元素是结构体的,可在结构体内部定义比较函数,下面按照id,length,width升序排序。
bool operator< (const Rect_fun &a) const
{
if(x != a.x)
return x<a.x;
else
{
if(flag !=a.flag)
return flag>a.flag;
else
{
if(flag==1)
return height>a.height;
else
return height<a.height;
}
}
}
};
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) {
vector<vector<int>> out;//输出的结果
vector<Rect_fun> state;
vector<int> now_height;//当前的高度
HeightNode p_item(0,0);
HeightNode *p_height = &p_item;
int height_temp = 0;
int height_x = 0;//向上跳变时x的起点
bool height_flag = 0;//是否在构建新的矩形
for(int i=0; i<buildings.size(); i++)//获得跳变沿的信息,之后对所有跳变沿排序
{
Rect_fun temp1(buildings.at(i).at(0), 1, buildings.at(i).at(2));
Rect_fun temp2(buildings.at(i).at(1), 0, buildings.at(i).at(2));
state.push_back(temp1);
state.push_back(temp2);
}
sort(state.begin(),state.end());
for(int i=0; i<state.size(); i++)
{
if(state.at(i).flag == 1)//如果是上升沿
{
//now_height.push_back(state.at(i).height);
addHeight(p_height,state.at(i).height);
if(0 == height_flag)//如果之前没有矩形
{
height_x = state.at(i).x;//记录下当前跳变沿的位置
height_temp = state.at(i).height;//记录下当前的高度
height_flag = 1;
}
else
{
if(state.at(i).height > height_temp)
{
vector<int> temp;
temp.push_back(height_x);
temp.push_back(state.at(i).x);
temp.push_back(height_temp);
out.push_back(temp);
height_x = state.at(i).x;
height_temp = state.at(i).height;
}
}
}
if(state.at(i).flag == 0)//如果是下降沿
{
//vector<int>::iterator iter=find(now_height.begin(), now_height.end(), state.at(i).height);
//now_height.erase(iter);
deleteHeight(p_height, state.at(i).height);
//if(now_height.size() != 0)
if(getHeightSize(p_height) != 0)
{
if(state.at(i).height != height_temp)//当去除的节点不是最大值,可以忽略
{
continue;
}
//int max_temp = *max_element(now_height.begin(),now_height.end());
int max_temp = findHeightMax(p_height);
if(max_temp < height_temp && height_x != state.at(i).x)//当前向下跳变比之前低,如果想下跳是最大值,但是有两个最大值,这句话可以避免问题
{
vector<int> temp;
temp.push_back(height_x);
temp.push_back(state.at(i).x);
temp.push_back(height_temp);
out.push_back(temp);
height_x = state.at(i).x;
height_temp = max_temp;
}
}
else//向下跳变到0
{
vector<int> temp;
temp.push_back(height_x);
temp.push_back(state.at(i).x);
temp.push_back(height_temp);
out.push_back(temp);
height_x = 0;
height_temp =0;
height_flag = 0;
}
}
}
return out;
// write your code here
}
};