题目来源
题目描述
class Solution {
public:
vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
}
};
题目解析
题意
题目中说:「关键点是水平线段的左端点」。我们把关键点的特点再说得具体一点:如果把天际线「从左到右」一笔画出来(如下图黄色线的运动轨迹所示),「关键点」是转折点,「关键点」不会在线段「中间」的部分。
可以看出,轮廓线的产生只来自于最大高度的变化
分析例子:轮廓线的产生只来自于最大高度的变化
如果有了新的单独的大楼,就相当于重新从0高度1开始跟踪
问题是:怎么跟踪最大高度呢?
流程
class Solution {
struct Node{
int x;
int h;
bool isAdd;
Node(int x, bool isAdd, int h) : x(x), h(h), isAdd(isAdd){
}
};
template <typename T>
inline const typename T::key_type& last_key(const T& pMap)
{
return pMap.rbegin()->first;
}
public:
vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
int N = buildings.size();
std::vector<Node *> nodes(N * 2);
for (int i = 0; i < N; ++i) {
nodes[i * 2] = new Node(buildings[i][0], true, buildings[i][2]);
nodes[i * 2 + 1] = new Node(buildings[i][1], false, buildings[i][2]);
}
std::sort(nodes.begin(), nodes.end(), [](Node * a, Node * b){
return a->x < b->x; // leetcode没有出现纸片大楼,所以只用一维数据排序
});
/* 2, +10 map[+10] = 1, m[2] = 10 0--->10
* 3, +15 map[+15] = 1, m[3] = 15 0--->10--->15
* 5, +12 map[+12] = 1, m[5] = 15
* 7, -15 map[+15] = 0, m[7] = 12
* 9, -10 map[+10] = 0, m[9] = 12
* 12, -12
* 15, +10
* 20, -10
* 19, +8
* 24, -8
*
* */
// map中需要拿到当前最大的key
std::map<int, int> mapHeightTimes;
std::map<int, int> maxXheight; // 因为最终答案我们要根据x排序,所以用map
for (auto & node : nodes) {
if(node->isAdd){
mapHeightTimes[node->h]++;
}else{
mapHeightTimes[node->h]--;
if(mapHeightTimes[node->h] == 0){
mapHeightTimes.erase(node->h);
}
}
//
// [2, 0], []
if(mapHeightTimes.empty()){
maxXheight[node->x] = 0;
}else{
maxXheight[node->x] = last_key(mapHeightTimes);
}
}
vector<vector<int>> ans;
for(auto entry : maxXheight){
int curX = entry.first;
int curMaxHeight = entry.second;
if(ans.empty() || ans.back()[1] != curMaxHeight){
ans.push_back({curX, curMaxHeight});
}
}
return ans;
}
};
类似题目
题目 | 思路 |
---|---|
leetcode:699. 掉落的方块 Falling Squares | |
leetcode:218. 天际线问题 The Skyline Problem | |
leetcode:850. 矩形面积之二 Rectangle Area II |
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。