支線任務5-skyline problem

1、題目描述(leetcode平臺天際線問題:https://leetcode.com/problems/the-skyline-problem/)java

A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skyline formed by these buildings collectively (Figure B).python

Buildings Skyline Contour

The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left and right edge of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX0 < Hi ≤ INT_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.c++

For instance, the dimensions of all buildings in Figure A are 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 [ [x1,y1], [x2, y2], [x3, y3], ... ] that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.編程

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

Notes:數據結構

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

 

2、解題思路ide

  最開始看到題目,我大體腦補了一下解決過程,發現感受並非太複雜,後來才發現是我太天真!沒有get到其中的玄機……不事後來在我擴充了對一些原來不多使用的數據結構的瞭解以後,最後的代碼實現也並非十分困難。測試

 

  最開始我拿到題目,想到的就是使用掃描線的思想,以橫軸爲基準逐段掃描整個座標軸,直至結束。在掃描的過程當中對每個節點的高度值進行確認,這樣只須要掃描一次就可以完成整個功能的實現。ui

  後來我發現,我最開始想的邊讀取邊掃描的方式是很難達到目的的。在讀取過程當中,因爲沒法預判後面讀取的數據是否會落在我目前掃描的這一段線段之中,會使整個工做變的較爲複雜。我也想過利用int的離散性逐點去進行肯定,但當數據量較大時,這些方式的時間複雜度都過大。

  在遇到一些障礙以後,我決定從人類的天然方式去畫線時實際用到的判斷來找算法的思路。當咱們本身畫線時,咱們遇到高度變化時(上升或降低),所畫天際線的高度也會隨之變化,而咱們在畫線時,永遠只盯着最高的那一條水平線,而沒有管在其之下有多少條水平線。而在高度須要降低時,咱們將會將高度降低至該點下方目前最高的一條線。因此問題的關鍵就在於,咱們如何獲取下方最高的一條線的高度。顯然,咱們須要一種容器,存儲多個水平線條的高度(也就是覆蓋正被掃描座標的各個線段高度),同時,咱們要可以從該容器之中獲取其中的最大值。顯然,咱們可使用動態數組,或向量,再本身排序來實現這個功能,但爲了簡化代碼,我採用了multiset多重集來實現,由於由STL庫的說明,該類可以自動依據給定的key將其排序,這將省去咱們的不少工做。一樣的,咱們在從左至右掃描時,也須要知道各個點的橫座標的排序,所以我也選用了multimap類來幫我實現這個功能。

  由此我獲得了一下算法的思路:

  1. 讀取全部的線段信息,將其轉化爲全部的左右端點的信息,並將全部端點的橫縱座標存儲在一個multimap中,咱們令一條水平線段的右端點在multimap中存儲的高度爲其自己高度的相反數,這樣咱們就能經過高度正負來判斷這是一條線段的首節點仍是尾節點。

  2. 此時咱們已經得到了全部的端點的信息,並獲得了他們的升序排列。因而咱們從橫座標最小的點開始,遇到一個點,若其高度爲整數,將其高度添加到一個multiset集中,這個集中存儲的就是目前正被掃描的線段的高度。若其高度爲負數,咱們就在集合中找到高度與其絕對值相等的元素,並將其刪除。這樣,咱們能夠保證multiset中永遠只存儲有被掃描中的線段的高度。

  3. 下面是如何在掃描時對節點高度進行修改。

  因爲題目要求,若同一橫座標有多個點,則只取其中最高的那個點,若最高的點高度與前一個點高度相等,則它應該被刪除。

  由此,我建立了一個pair<int,int>類變量t_x來存儲被掃描過的點的座標。若是遇到的下一個點與t_x橫座標相等,則將t_x縱座標修改成其中較大的值。若是遇到的下一個點與t_x橫座標不等,則說明t_x應該被壓入results(存儲最後返回的結果的向量)之中,此時咱們須要判斷,t_x的高度是否與results中存儲的最後一個節點的縱座標相等,若相等,則說明這依舊是一條水平的線條,那麼t_x不該被壓入results中。反之,壓入。以後將t_x更新爲新的橫縱座標。橫座標爲下一個點的橫座標,而縱座標則爲multiset中當前的最大值。重複這樣的操做直至結束,再對開頭結束的一些特殊狀況進行特判,就將獲得咱們須要的結果。將results向量返回便可。

 

3、代碼實現

 

 

具體代碼如圖,已經經平臺測試提交經過,因爲代碼註釋寫的較多故在此就不對代碼細節再進行過多闡述。

 

4、總結

  本次的小練習仍是讓我略略的瞭解了一些高級數據結構的使用的,例如set和map等,對個人編程水平仍是有必定程度的提升。另外我也很好奇爲何java和python寫出來的程序比c++要快很多。最後,關於世辰巨巨說的題目太簡單的問題,小白表示,這個難度就已經夠咱們喝一壺了ORZ(此處爲破涕爲笑表情)

相關文章
相關標籤/搜索