diff --git a/README.md b/README.md index a6db914..1d42278 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,7 @@ My LeetCode solutions with Chinese explanation. 我的LeetCode中文题解。 | 215 |[Kth Largest Element in an Array](https://leetcode.com/problems/kth-largest-element-in-an-array/)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/215.%20Kth%20Largest%20Element%20in%20an%20Array.md)|Medium| | | 216 |[Combination Sum III](https://leetcode.com/problems/combination-sum-iii/)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/216.%20Combination%20Sum%20III.md)|Medium| | | 217 |[Contains Duplicate](https://leetcode.com/problems/contains-duplicate)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/217.%20Contains%20Duplicate.md)|Easy| | +| 218 |[The Skyline Problem](https://leetcode.com/problems/the-skyline-problem/)|[C++](solutions/218.%20The%20Skyline%20Problem.md)|Hard| | | 219 |[Contains Duplicate II](https://leetcode.com/problems/contains-duplicate-ii)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/219.%20Contains%20Duplicate%20II.md)|Easy| | | 220 |[Contains Duplicate III](https://leetcode.com/problems/contains-duplicate-iii/)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/220.%20Contains%20Duplicate%20III.md)|Medium| | | 221 |[Maximal Square](https://leetcode.com/problems/maximal-square/)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/221.%20Maximal%20Square.md)|Medium| | diff --git a/solutions/218. The Skyline Problem.md b/solutions/218. The Skyline Problem.md new file mode 100644 index 0000000..e61105d --- /dev/null +++ b/solutions/218. The Skyline Problem.md @@ -0,0 +1,48 @@ +# [218. The Skyline Problem](https://leetcode.com/problems/the-skyline-problem/) + +# 思路 + +扫描法 + +想象一下从左到右扫描,如果当前扫描线穿过的building的最大高度与上一次的最大高度不一样,说明遇到了转折点,记录这个转折点即可。 + +首先为了从左到右扫描,我们需要将所有边界(包括左边界和右边界)与高度的pair按照水平位置排序(为了区分左右边界,将左边界的高度存为负数,建立左边界和负高度的pair); + +然后,我们还需要用一个容器记录当前扫描线穿过的building的所有高度,而且能够快速获得最大高度以及删除某个高度,那么`multiset`就很不错。我们先插入高度0为初始高度,然后开始扫描,如果遇到高度为负值的pair,说明是左边界,那么将高度插入multiset中;否则说明遇到了右边界,应该从multiset中删除这个高度。然后取出此时multiset中最高的高度,判断是否等于上一轮的最大高度,若不是则表示遇到了转折,需要存放到结果数组中。 + +扫描过程动图可参考[此处](https://leetcode-cn.com/problems/the-skyline-problem/solution/218tian-ji-xian-wen-ti-sao-miao-xian-fa-by-ivan_al/) + +时间复杂度O(nlogn);空间复杂度O(n) + +# C++ +``` C++ +class Solution { +public: + vector> getSkyline(vector>& buildings) { + vector>all; + vector>res; + multisetst; + + for(auto &b: buildings){ + all.push_back({b[0], -b[2]}); // 左边界, -高度 + all.push_back({b[1], b[2]}); // 右边界, 高度 + } + sort(all.begin(), all.end()); // 将边界排好序 + + int pre_h = 0, cur_h; + st.insert(0); + for(auto &b: all){ // 从左至右扫描 + if(b.second < 0) st.insert(-b.second); + else st.erase(st.find(b.second)); + + cur_h = *st.rbegin(); // 当前最高高度 + if(cur_h != pre_h){ + res.push_back({b.first, cur_h}); + pre_h = cur_h; + } + } + return res; + } +}; +``` +