📜  天际线问题套装2

📅  最后修改于: 2021-04-23 19:33:57             🧑  作者: Mango

给定一个二维城市中的n座矩形建筑物,可以计算这些建筑物的天际线,从而消除隐藏线。主要任务是从一边查看建筑物,然后删除所有不可见的部分。
所有建筑物都具有共同的底部,并且每栋建筑物都由一个三元组表示(左,ht,右)

  • 左:在左侧(或墙壁)上x坐标。
  • 右:是右侧的x坐标。
  • ht:是建筑物的高度。

天际线是矩形带的集合。矩形带表示为一对(左,ht),其中,左是带左侧的x坐标,而ht是带的高度。

例子:

方法:

  1. 从每个建筑物的给定三元组中,检索左墙位置,高度和右墙位置值。
  2. 将左墙的负高度值和右墙的实际高度成对存储在向量墙中。这样做是为了区分同一建筑物的左墙和右墙。
  3. 按升序对墙壁进行排序。
  4. 遍历矢量(如果找到了左墙),则将左墙的高度存储在多重集M中。否则,如果遇到右墙,则从多重集中删除其对应的高度。
  5. 检查最高值是否已更改。如果它已更改,则更新最高值,并将当前墙的横坐标(x坐标)值和更新的最高值存储在vector中,作为skyline
  6. 打印存储在天际线矢量中的值对。

下面是上述方法的实现:

C++
// C++ progrqam for the above approach
#include 
using namespace std;
  
// Function to create skyline
vector >
createSkyline(vector >& buildings)
{
  
    // Get the number of buildings
    int N = buildings.size();
  
    // To store the left and right
    // wall position of the buildings
    vector > 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 > skyline;
  
    // Initialize a multiset to
    // keep left wall heights sorted
    multiset 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 >& buildings)
{
  
    // Function call for creating skyline
    vector > skyline
        = createSkyline(buildings);
  
    cout << "Skyline for given"
         << " buildings:\n{";
  
    for (auto it : skyline) {
  
        cout << "{" << it.first << ", "
             << it.second << "} ";
    }
    cout << "}";
}
  
// Driver Code
int main()
{
    vector > buildings;blockquote
  
    // 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;
}


输出:

时间复杂度: O(N * log(N))
辅助空间: O(N)