LeetCode 218. The Skyline Problem

方法一:Line Sweep

几何类问题,可以用 Line Sweep nlogn 解决。维护一个active set,左边界进右边界出。排序时注意 corner cases:

1. 右边界和左边界x一样时,先处理左边界。

2. 多个左边界x一样时,高的先处理。

3. 多个右边界x一样时,矮的先处理。

sort的时候使用 e1.h*e1.type > e2.h*e2.type 判断,包括了上述三种情况,即 h*type 大的排在前面。

由于active set中可能有重复元素出现,用multiset erase的时候比较麻烦。因此用 {h, id} 这个pair来避免重复元素。

class Solution {
public:
    struct edge {
        int x;
        int h;
        int id;
        int type; // left <- 1, right <- -1
    };
    
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
        vector<edge> vec;
        
        int id=0;
        for (auto b:buildings){
            vec.push_back({b[0],b[2],id,1});
            vec.push_back({b[1],b[2],id,-1});
            ++id;
        }
        
        sort(vec.begin(),vec.end(),[](edge e1, edge e2){
            if (e1.x==e2.x){ // contains all the corner cases
                return e1.h*e1.type > e2.h*e2.type;
            }
            return e1.x < e2.x;
        });
        
        vector<vector<int>> res;
        set<pair<int,int>> active_set; // <h,id>
        for (edge e:vec){
            if (e.type==1){ // left edge
                if (active_set.empty() || e.h > rbegin(active_set)->first){
                    res.push_back({e.x,e.h});
                }
                active_set.insert({e.h,e.id});
            }else{ // right edge
                active_set.erase({e.h,e.id});
                if (active_set.empty()) res.push_back({e.x,0});
                else if (e.h > rbegin(active_set)->first){
                    res.push_back({e.x,rbegin(active_set)->first});
                }
            }
        }
    
        return res;
    }
};

时间复杂度 O(nlogn)

 

posted @ 2019-07-24 15:43  約束の空  阅读(131)  评论(0)    收藏  举报