New Skyline Problem approach: only list

New approach to Skyline Problem. 82% time and 99,9% space
Worst case time 0(N2), expected time close to O(N)
Idea is consequently merge buildings util no intersections left

class Solution {
    struct Building
    {
        int x1 = 0;
        int x2 = 0;
        int h = 0;
        
        Building()
        {}
        
        Building(const vector<int> &source)
            : x1(source[0]),
            x2(source[1]),
            h(source[2])
        {}
        
        static bool isAfter(const Building &b1, const Building &b2)
        {
            return b1.x2 < b2.x1;
        }
        
        static bool isIntersect(const Building &b1, const Building &b2)
        {
            if(b1.x2<b2.x1 || b2.x2<b1.x1)
                return false;
            if(b1.x1==b2.x2 || b1.x2==b2.x1)
                return false;
            return true;
        }
        
        static int merge(Building &b1, Building &b2, Building &extra)
        {
            if(b2.x2<b1.x1)
                swap(b1,b2);
            // Same height buildings. Just join
            if(b1.h == b2.h)
            {
                int x1 = min(b1.x1, b2.x1);
                int x2 = max(b1.x2, b2.x2);
                b1.x1 = x1;
                b1.x2 = x2;
                return 1;
            }
            // Two neighbours buildings with common middle wall. Do nothing
            if(b1.x2==b2.x1 || b2.x2==b1.x1)
                return 2;
            // Two equals walls
            if(b1.x1==b2.x1 && b2.x2==b1.x2)
            {
                if(b2.h>b1.h)
                    swap(b1, b2);
                return 1;
            }
            
            // one inside another
            if(b1.x1<b2.x1 && b2.x2<b1.x2)
            {
                // Tallest outside
                if(b1.h>b2.h)
                    return 1;
                // Tallest inside
                extra.x2 = b1.x2;
                b1.x2 = b2.x1;
                extra.x1 = b2.x2;
                extra.h = b1.h;
                return 3;
            }
            // Just overlapping
            // Common wall
            if(b1.x1==b2.x1 || b1.x2==b2.x2)
            {
                // Most wide to first position
                if(b1.x2-b1.x1 < b2.x2-b2.x1)
                    swap(b1,b2);
                if(b1.h>b2.h)
                     return 1;
                if(b1.x1==b2.x1)
                {
                    swap(b1, b2);
                    b2.x1 = b1.x2;
                }
                else
                {
                    b1.x2 = b2.x1;
                }
                return 2;
            }
            if(b1.h > b2.h)
            {
                b2.x1 = b1.x2;
            }
            else
            {
                b1.x2 = b2.x1;
            }
            return 2;
        }
    };
    
public:
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {

        list<Building> line;
        auto it = buildings.begin();
        line.push_back(Building(*it));
        Building extra;
        for(++it; it!=buildings.end(); ++it)
        {
            auto itLine=prev(line.end());
            Building b2(*it);
            if(Building::isAfter(*itLine, b2))
            {
                line.push_back(b2);
            }
            else
            {
                while(itLine != line.begin())
                {
                    auto itPrev=prev(itLine);
                    if(Building::isAfter(*itPrev, b2))
                        break;
                    itLine = itPrev;
                }
                int n = Building::merge(*itLine, b2, extra);
                if(n<=2)
                {
                    auto itPrev=itLine;
                    ++itLine;
                    if(n==2)
                        itPrev=line.insert(itLine, b2);
                    while(itLine != line.end() && itLine != itPrev && Building::isIntersect(*itPrev, *itLine))
                    {
                        if(Building::merge(*itPrev, *itLine, extra) == 1)
                            itLine = line.erase(itLine);
                        else
                        {
                            ++itLine;
                            ++itPrev;
                        }
                    }
                }
                if(n==3)
                {
                    ++itLine;
                    line.insert(itLine, b2);
                    line.insert(itLine, extra);
                }
            }
        }
        
        int lastX=-1;
        vector<vector<int>> ret;
        for(const auto &b : line)
        {
            if(lastX>0 && b.x1!=lastX)
                ret.push_back({lastX, 0});
            ret.push_back({b.x1, b.h});
            lastX = b.x2;
        }
        ret.push_back({line.back().x2, 0});
        return ret;
    }
};
Comments (2)