leetcode 218 天際線問題
阿新 • • 發佈:2021-11-06
初次見到確實是比較困難的問題。解決問題的關鍵在於抽象出答案中水平線段的端點一定是某一建築的左端點或者右端點,而如果是右端點作為端點,則該建築的高度對於這個水平線段並不產生影響(最後一個建築後的高度為0的天際線就是一個例子)。所以可以考慮遍歷所有的端點,對某一個端點而言,考慮所有包含該端點的建築,其中最高的自然就是以該端點為起始點的天際線的高度,這一部分的比較可以使用優先佇列來完成。這裡還會用到一個延遲刪除的技巧,對於某一個端點,並不需要刪除所有不滿足要求的建築,而是隻要當前佇列中的最大值的建築包含該端點即可,若當前最大值並不包含該端點,則彈出該建築,重複該過程知道當前top節點滿足要求。而在建築進入優先佇列之後,判斷是否需要彈出佇列的依據只有該建築的右端點與高度值,所以優先佇列中只需要維護一個二元組即可。貼程式碼
1 class Solution { 2 public: 3 vector<vector<int>> getSkyline(vector<vector<int>>& buildings) 4 { 5 auto cmp = [](const pair<int, int>& a, const pair<int, int>& b) -> bool { return a.second < b.second; }; 6 priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(cmp)> que(cmp); 7 vector<int> boundaries; 8 for(auto& building:buildings) 9 { 10 boundaries.emplace_back(building[0]); 11 boundaries.emplace_back(building[1]); 12 }13 sort(boundaries.begin(),boundaries.end()); 14 15 vector<vector<int>> ret; 16 int n = buildings.size(); 17 int index = 0; 18 for(auto boundary:boundaries) 19 { 20 //建築處於當前範圍內 21 while(index<n && boundary>=buildings[index][0]) 22 { 23 que.emplace(buildings[index][1],buildings[index][2]); 24 index++; 25 } 26 while(!que.empty() && que.top().first<=boundary) 27 que.pop(); 28 int maxn = que.empty()?0:que.top().second; 29 if(ret.size() == 0 || ret.back()[1]!=maxn) 30 ret.push_back({boundary,maxn}); 31 } 32 return ret; 33 } 34 };