Leetcode-the Skyline problem

Source: Internet
Author: User

I. Topic Leetcode skyline issues on the platform

A city's skyline is the outer contour of the silhouette formed by all the buildings in then city then viewed from a Distan Ce. Now suppose you is given the locations and height of all the buildings as shown in a cityscape photo (figure A), write a Program to output the skyline formed by these buildings collectively (Figure B).

The geometric information of each building was represented by a triplet of integers [Li, Ri, Hi] , where and is the Li Ri x Coordinates of the left and right edge of the ith building, respectively, and are its Hi height. It's guaranteed that 0 ≤ Li, Ri ≤ INT_MAX , 0 < Hi ≤ INT_MAX and Ri - Li > 0 . Assume all buildings is perfect rectangles grounded on a absolutely flat surface at height 0.

For instance, the dimensions of all buildings in Figure A is recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ]  .

The output is a list of "key points" (Red dots in Figure B) in the format of that [ [x1,y1], [x2, y2], [x3, y3], ... ] uniquely defines a skyline. A key point was the left endpoint of a horizontal line segment. Note the last key point, where the rightmost building ends, was merely used to mark the termination of the skyline, an D always have zero height. Also, the ground in between any and adjacent buildings should is considered part of the Skyline Contour.

For instance, the skyline in Figure B should is represented as: [ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ] .

Notes:

    • The number of buildings in all input list is guaranteed to being in the range [0, 10000] .
    • The input list is already sorted in ascending order by the left X position Li .
    • The output list must is sorted by the X position.
    • There must is no consecutive horizontal lines of equal height in the output skyline. For instance, was not [...[2 3], [4 5], [7 5], [11 5], [12 7]...] acceptable; The three lines of height 5 should being merged into one in the final output as such:[...[2 3], [4 5], [12 7], ...]

Two. Solving ideas

Meng New in just see this problem when said is not the beginning, and later in the giant blog to see the time line tree this data structure, feel this data structure is really very good ah, is also very suitable to solve the problem ~

First put on a line to explain the tree segment of the blog, but also from the time of the blog, I feel that the explanation of the line tree is really vivid image, the sample is also very enlightening.

Line Segment Tree Blog

As the author of the above blog mentions:

Each node in a segment tree tends to add some additional fields. Some of the dynamic maintenance information is stored in these domains, depending on the situation. These fields make the segment tree extremely flexible and adaptable to different requirements.

This passage embodies the benefits of the flexibility of the line-segment tree, and in order to adapt to this problem, I have designed this line-of-tree data structure:

typedef struct SEGMENTNODE{INT start;        Interval left end of segment tree int end;      The interval of the segment tree has the endpoint int isflat;      Whether the skyline within the current interval is a horizontal int height;  If Isflat equals 1, represents the height of the current interval skyline, otherwise meaningless segmentnode* left;  Left son segmentnode* right; Right son}segmentnode;

The idea is that the initial skyline is a horizontal line with a height of 0, and each addition of a rectangle (corresponding to the operation of the segment tree insertion node) updates the skyline.

Assuming that there is already a skyline, when you add a rectangle on this basis, for one of the endpoints of the segment tree, if the interval it represents contains the interval of the newly added rectangle, there are several possible scenarios for the skyline to change:

1. The original skyline is horizontal

If the rectangle height is less than or equal to the original height, the skyline will not change

If the height of the rectangle is greater than the original height, if the rectangle's interval is exactly equal to the interval represented by the segment tree node, the height value of the node is directly updated to be rectangular. If the interval of the rectangle is less than or equal to the interval of the segment tree node, then the Isflat value of the node is reset to 0, and the left and right subtree of the endpoint is recursive until it finds the end of the segment tree that is exactly equal to the interval of the rectangle, and one thing to note here is that if the rectangle and the left and right nodes , you need to split the rectangle into two rectangles to operate.

2. The original skyline is not horizontal, then the left and right subtree of the endpoint is recursive until the endpoint of the isflat=1 is found.

The above procedure is performed during the insertion of a segment tree node, and the code for inserting a node function is as follows:

void Insertnode (int l, int r, int h, segmentnode* tree)//Because this function is called recursively, it is guaranteed that the rectangular range {if (!tree) return;if in the corresponding node interval (tree-&gt ; isflat)//Current Horizon Horizon level {int mid = TREE-&GT;START/2 + tree->end/2;if ((tree->start% 2) &                    & (tree->end% 2)) mid++; Find the middle node of the interval if (H <= tree->height)//The current range of Skyline Heights is greater than the rectangular height return;if (Tree->start = = L && tree-> end = = r)//The current interval is the rectangular interval {tree->height = H;return;} else if (Mid >= R)//rectangle is all in the interval represented by Zuozi {Tree->isflat = 0;if (!tree->left) {tree->left = Createtree ( Tree->start, mid); tree->right = Createtree (Mid, tree->end); tree->right->height = tree->height; Tree->left->height = Tree->height;} Insertnode (L, R, H, Tree->left),//insertnode (Mid, Tree->end, Tree->height, tree->right);} else if (Mid <= L)//rectangle is all in the right sub-tree corresponding interval {Tree->isflat = 0;if (!tree->right) {tree->left = c Reatetree (Tree->start,mid); tree->right = Createtree (Mid, tree->end); tree->left->height = tree->height;tree->right-> Height = tree->height;} Insertnode (L, R, H, tree->right);} else//rectangle spans the left and right sub-tree interval {Tree->isflat = 0;if (!tree->left) {tree->left = Createtree (t Ree->start, mid); tree->right = Createtree (Mid, tree->end); tree->left->height = tree->height;tree- >right->height = Tree->height;} Insertnode (L, Mid, H, Tree->left), Insertnode (Mid, R, H, Tree->right);}}  else//Current segment tree Uneven {int mid = TREE-&GT;START/2 + tree->end/2;if (tree->start % 2) && (tree->end% 2) mid++;if (Tree->start = = L && tree->end = r) {Insertnode (L, Mid, H, tree- >left); Insertnode (Mid, R, H, tree->right);} else if (Mid >= R) {Insertnode (L, R, H, Tree->left);} else if (Mid <= L) {Insertnode (L, R, H, tree->right);} Else{insertnode (L, Mid, H, Tree->left); Insertnode (Mid, R,h, tree->right);}}} 

Then after all the rectangles have been added, the sequence traversal of the segment tree is carried out, and all the leaf nodes of the segment tree store the information of the skyline. Finally, the test code submitted on the Leetcode platform is this (because the code part of the line tree is commented, the corresponding section is no longer annotated):

typedef struct SEGMENTNODE{INT start;int end;int isflat;int height; Segmentnode* left; segmentnode* right;} Segmentnode; segmentnode* createtree (int leftrange, int rightrange)//initialization of line segment Tree {segmentnode* tree = new Segmentnode;tree->sta  RT = Leftrange;tree->end = Rightrange;tree->left = Null;tree->right = Null;tree->isflat = 1;tree->height = 0;return Tree;}  void Insertnode (int l, int r, int h, segmentnode* tree) {if (!tree) return;if (tree->isflat) {int mid = TREE-&GT;START/2 + Tree->end/2;if ((tree->start% 2) && (tree->end% 2)) mid++;if (H <= tree->height) return;if (tree-& Gt;start = = L && tree->end = = r) {tree->height = H;return;} else if (Mid >= r) {Tree->isflat = 0;if (!tree->left) {tree->left = Createtree (Tree->start, mid);tree-> right = Createtree (mid, tree->end); tree->right->height = Tree->height;tree->left->height = tree- >height;} Insertnode (L, R, H, Tree->left);//insertnode (Mid, Tree->end, Tree->height, tree->right);} else if (Mid <= l) {Tree->isflat = 0;if (!tree->right) {tree->left = Createtree (Tree->start, mid);tree-> right = Createtree (mid, tree->end); tree->left->height = Tree->height;tree->right->height = tree- >height;} Insertnode (L, R, H, tree->right);} Else{tree->isflat = 0;if (!tree->left) {tree->left = Createtree (Tree->start, mid); tree->right = Createtree (Mid, tree->end); tree->left->height = Tree->height;tree->right->height = tree-> Height;} Insertnode (L, Mid, H, Tree->left), Insertnode (Mid, R, H, Tree->right);}} Else{int mid = Tree->start/2 + tree->end/2;if ((tree->start% 2) && (tree->end% 2)) Mid++;if (tree-& Gt;start = = L && tree->end = = r) {Insertnode (L, Mid, H, Tree->left); Insertnode (Mid, R, H, tree->right);} else if (Mid >= R) {Insertnode (L, R, H, Tree->left);} else if (Mid <= L) {Insertnode (L, R, H, tree->right);} Else{insertnode (L, Mid, h, Tree->left); Insertnode (Mid, R, H, Tree->right);}}} void GetResult (segmentnode* tree, vector<pair<int, int>>& result, int& lastheight) {if (!tree) Return;pair<int, int> temp;if (Tree->isflat)//if the corresponding interval of the node is flat, the result is obtained, otherwise the left and right subtree is recursively {Temp.first = Tree->start;temp.second = Tree->height;if (temp.second! = lastheight)//If the node height is equal to the previous node height, indicating that the skyline does not bend, do not output this Node Information {result.push_back (temp);} Lastheight = Temp.second;return;} Else{getresult (Tree->left, result, lastheight); GetResult (tree->right, result, lastheight);}} Class Solution {Public:vector<pair<int, int>> getskyline (vector<vector<int>>& buildings ) {int rightrange = 0;for (int i = 0; i < buildings.size (); i++) {if (buildings[i][1] > Rightrange) rightrange = Buildin                                                  GS[I][1];} Determines the interval range of the root node of a segment segmentnode* tree = Createtree (0, Rightrange); for (int i = 0; i < buildings.size (); i++) {Insertnode (Buil DingS[i][0], buildings[i][1], buildings[i][2], tree); Insert a rectangle one by one, update the Skyline}vector<pair<int, int>> result;int lastheight = 0;int Lastpos = 0;getresult (tree, result,                            Lastheight);                                Get the Skyline pair<int, int> temp;temp.first = Rightrange;temp.second = 0;if (rightrange) result.push_back (temp); Add the last node of the skyline return result;};

During the commit process, there were some problems: at first I created a complete binary tree when I built the line segment tree, and the result was a memory limit exceeded error in the test sample [0, 2147483647, 2147483647]. Later, in the new segment tree to create only new root node, in the process of inserting nodes and then request space as needed, the problem has been resolved; there are a variety of errors, basically because of their own brain residue caused by ...

The result of the final submission, you can see the speed is still very fast, probably because the result of not using STL.

  

Three. Summary

The process of solving this problem is still very fruitful, mainly embodied in the data structure of the line segment tree has a preliminary understanding of the process of debugging code let me have a new understanding of what I might commit a variety of errors, feel posture level has been improved. Finally, if you see my blog, I hope that we learn together, progress together ~

Leetcode-the Skyline problem

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.