Open In App

The Skyline Problem | Set 2

Given n rectangular buildings in a 2-dimensional city, computes the skyline of these buildings, eliminating hidden lines. The main task is to view buildings from aside and remove all sections that are not visible. 

All buildings share a common bottom and every building is represented by a triplet (left, ht, right) 



A skyline is a collection of rectangular strips. A rectangular strip is represented as a pair (left, ht) where left is x coordinate of the left side of the strip and ht is the height of the strip.

Examples: 



Input: buildings[][] = { {1, 11, 5}, {2, 6, 7}, {3, 13, 9}, {12, 7, 16}, {14, 3, 25}, {19, 18, 22}, {23, 13, 29}, {24, 4, 28} }
Output: { {1, 11}, {3, 13}, {9, 0}, {12, 7}, {16, 3}, {19, 18}, {22, 3}, {23, 13}, {29, 0} }
Explanation:
The skyline is formed based on the key-points (representing by “green” dots) 
eliminating hidden walls of the buildings.
 

Input: buildings[ ][ ] = { {1, 11, 5} }
Output: { {1, 11}, {5, 0} }

The Skyline Problem Using MultiSet:

Approach: 

Below is the implementation of the above approach: 




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to create skyline
vector<pair<int, int> >
createSkyline(vector<vector<int> >& buildings)
{
 
    // Get the number of buildings
    int N = buildings.size();
 
    // To store the left and right
    // wall position of the buildings
    vector<pair<int, int> > wall;
 
    // Triplet of building structure
    // parameters
    int left, height, right;
    for (int i = 0; i < N; i++) {
 
        // Get left point of building
        left = buildings[i][0];
 
        // Get height of building
        height = buildings[i][1];
 
        // Get right point of building
        right = buildings[i][2];
 
        // Store left point and height
        // of the left wall
 
        // Negative value means left wall
        // will be inserted to multiset first
        // for the same abscissa(x) as right wall
        wall.push_back({ left, -height });
 
        // Store right point and height
        // of the right wall
        wall.push_back(
            make_pair(right, height));
    }
 
    // Sort the walls in ascending order
    sort(wall.begin(), wall.end());
 
    // To store skyline: output
    vector<pair<int, int> > skyline;
 
    // Initialize a multiset to
    // keep left wall heights sorted
    multiset<int> leftWallHeight = { 0 };
 
    // Current max height among
    // leftWallHeights
    int top = 0;
 
    // Traverse through the sorted walls
    for (auto w : wall) {
 
        // If left wall is found
        if (w.second < 0) {
 
            // Insert the height
            leftWallHeight.insert(-w.second);
        }
 
        // If right wall is found
        else {
 
            // Remove the height
            leftWallHeight.erase(
                leftWallHeight.find(w.second));
        }
 
        // Mark a skyline point if top changes
        // .rbegin(): reverse iterator
        if (*leftWallHeight.rbegin() != top) {
 
            top = *leftWallHeight.rbegin();
            skyline.push_back(
                make_pair(w.first, top));
        }
    }
 
    // Return skyline to printSkyline
    return skyline;
}
 
// Function to print the output skyline
void printSkyline(
    vector<vector<int> >& buildings)
{
 
    // Function call for creating skyline
    vector<pair<int, int> > skyline
        = createSkyline(buildings);
 
    cout << "Skyline for given"
         << " buildings:\n{";
 
    for (auto it : skyline) {
 
        cout << "{" << it.first << ", "
             << it.second << "} ";
    }
    cout << "}";
}
 
// Driver Code
int main()
{
    vector<vector<int> > buildings;
 
    // Given left and right location
    // and height of the wall
    buildings = { { 1, 11, 5 }, { 2, 6, 7 },
                  { 3, 13, 9 }, { 12, 7, 16 },
                  { 14, 3, 25 }, { 19, 18, 22 },
                  { 23, 13, 29 }, { 24, 4, 28 } };
 
    // Function Call
    printSkyline(buildings);
    return 0;
}




import java.util.*;
 
public class Skyline {
 
    public static List<int[]> createSkyline(int[][] buildings) {
        List<int[]> wall = new ArrayList<>();
        int N = buildings.length;
        int left, height, right;
        for (int i = 0; i < N; i++) {
            left = buildings[i][0];
            height = buildings[i][1];
            right = buildings[i][2];
            wall.add(new int[]{left, -height});
            wall.add(new int[]{right, height});
        }
        wall.sort((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
        List<int[]> skyline = new ArrayList<>();
        TreeSet<Integer> leftWallHeight = new TreeSet<>(Collections.singleton(0));
        int top = 0;
        for (int[] w : wall) {
            if (w[1] < 0) {
                leftWallHeight.add(-w[1]);
            } else {
                leftWallHeight.remove(w[1]);
            }
            int curTop = leftWallHeight.last();
            if (curTop != top) {
                top = curTop;
                skyline.add(new int[]{w[0], top});
            }
        }
        return skyline;
    }
 
    public static void printSkyline(int[][] buildings) {
        List<int[]> skyline = createSkyline(buildings);
        System.out.println("Skyline for given buildings:");
        System.out.print("{");
        for (int[] it : skyline) {
            System.out.print("{" + it[0] + ", " + it[1] + "} ");
        }
        System.out.println("}");
    }
 
    public static void main(String[] args) {
        int[][] buildings = {{1, 11, 5}, {2, 6, 7}, {3, 13, 9}, {12, 7, 16},
                {14, 3, 25}, {19, 18, 22}, {23, 13, 29}, {24, 4, 28}};
        printSkyline(buildings);
    }
}




# pyton equivalent code
from functools import cmp_to_key
 
def func(a, b):
    if(a[0] != b[0]):
        return a[0] - b[0]
    else:
        return a[1] - b[1]
     
def createSkyline(buildings):
     
    wall = []
    N = len(buildings)
    left = 0
    height = 0
    right = 0
    for i in range(N):
        left = buildings[i][0]
        height = buildings[i][1]
        right = buildings[i][2]
        wall.append([left, -height])
        wall.append([right, height])
     
    letter_cmp_key = cmp_to_key(func)
    wall.sort(key = letter_cmp_key)
    # wall.sort(func)
 
    skyline = []
    leftWallHeight = set()
    leftWallHeight.add(0)
     
    top = 0
    for w in wall:
        if w[1] < 0:
            leftWallHeight.add(-w[1])
        else:
            leftWallHeight.remove(w[1])
             
        curTop = max(leftWallHeight)
        if curTop != top:
            top = curTop;
            skyline.append([w[0], top])
 
    return skyline
 
def printSkyline(buildings):
 
    skyline = createSkyline(buildings)
    print('Skyline for given buildings:')
    temp = '{'
     
    for it in skyline:
        temp = temp + "{" + str(it[0]) + "," + str(it[1]) + "} "
 
    print(temp + '}')
 
 
buildings = [[1, 11, 5], [2, 6, 7], [3, 13, 9], [12, 7, 16],
[14, 3, 25], [19, 18, 22], [23, 13, 29], [24, 4, 28]]
 
printSkyline(buildings)
 
# The code is contributed by Nidhi goel.




// C# program for the above approach
using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
    static int func(int[] a, int[] b)
    {
        if (a[0] != b[0])
        {
            return a[0] - b[0];
        }
        else
        {
            return a[1] - b[1];
        }
    }
 
    static List<int[]> createSkyline(List<int[]> buildings)
    {
        List<int[]> wall = new List<int[]>();
        int N = buildings.Count;
        int left = 0;
        int height = 0;
        int right = 0;
        for (int i = 0; i < N; i++)
        {
            left = buildings[i][0];
            height = buildings[i][1];
            right = buildings[i][2];
            wall.Add(new int[] { left, -height });
            wall.Add(new int[] { right, height });
        }
 
        Comparison<int[]> letter_cmp_key = new Comparison<int[]>(func);
        wall.Sort(letter_cmp_key);
 
        List<int[]> skyline = new List<int[]>();
        SortedSet<int> leftWallHeight = new SortedSet<int>();
        leftWallHeight.Add(0);
 
        int top = 0;
        foreach (int[] w in wall)
        {
            if (w[1] < 0)
            {
                leftWallHeight.Add(-w[1]);
            }
            else
            {
                leftWallHeight.Remove(w[1]);
            }
 
            int curTop = leftWallHeight.Max;
            if (curTop != top)
            {
                top = curTop;
                skyline.Add(new int[] { w[0], top });
            }
        }
 
        return skyline;
    }
 
    static void printSkyline(List<int[]> buildings)
    {
        List<int[]> skyline = createSkyline(buildings);
        Console.WriteLine("Skyline for given buildings:");
        string temp = "{";
 
        foreach (int[] it in skyline)
        {
            temp = temp + "{" + it[0] + "," + it[1] + "} ";
        }
 
        Console.WriteLine(temp + "}");
    }
 
    static void Main(string[] args)
    {
        List<int[]> buildings = new List<int[]> {
            new int[] {1, 11, 5},
            new int[] {2, 6, 7},
            new int[] {3, 13, 9},
            new int[] {12, 7, 16},
            new int[] {14, 3, 25},
            new int[] {19, 18, 22},
            new int[] {23, 13, 29},
            new int[] {24, 4, 28}
        };
 
        printSkyline(buildings);
 
          
    }
}
// The code is contributed by shivamsharma215.




// Javascript equivalent code
 
const createSkyline = (buildings) => {
    let wall = [];
    let N = buildings.length;
    let left, height, right;
    for (let i = 0; i < N; i++) {
        left = buildings[i][0];
        height = buildings[i][1];
        right = buildings[i][2];
        wall.push([left, -height]);
        wall.push([right, height]);
    }
    wall.sort((a, b) => {
        if (a[0] !== b[0]) {
            return a[0] - b[0];
        } else {
            return a[1] - b[1];
        }
    });
    let skyline = [];
    let leftWallHeight = new Set([0]);
    let top = 0;
    for (let w of wall) {
        if (w[1] < 0) {
            leftWallHeight.add(-w[1]);
        } else {
            leftWallHeight.delete(w[1]);
        }
        let curTop = Math.max(...leftWallHeight);
        if (curTop !== top) {
            top = curTop;
            skyline.push([w[0], top]);
        }
    }
    return skyline;
}
 
const printSkyline = (buildings) => {
    let skyline = createSkyline(buildings);
    console.log('Skyline for given buildings:');
    temp = '{';
    for (let it of skyline) {
       temp = temp +`{${it[0]}, ${it[1]}} `;
    }
    console.log(temp + '}');
}
 
let buildings = [[1, 11, 5], [2, 6, 7], [3, 13, 9], [12, 7, 16],
[14, 3, 25], [19, 18, 22], [23, 13, 29], [24, 4, 28]];
 
printSkyline(buildings);

Output
Skyline for given buildings:
{{1, 11} {3, 13} {9, 0} {12, 7} {16, 3} {19, 18} {22, 3} {23, 13} {29, 0} }

Time Complexity: O(N logN)
Auxilary Space:O(N)
 


Article Tags :