【堆 (優先隊列) 掃描線】218. 天際線問題

本文涉及知識點

堆 (優先隊列) 掃描線

LeetCode218. 天際線問題

城市的 天際線 是從遠處觀看該城市中所有建筑物形成的輪廓的外部輪廓。給你所有建筑物的位置和高度,請返回 由這些建筑物形成的 天際線 。
每個建筑物的幾何信息由數組 buildings 表示,其中三元組 buildings[i] = [lefti, righti, heighti] 表示:
lefti 是第 i 座建筑物左邊緣的 x 坐標。
righti 是第 i 座建筑物右邊緣的 x 坐標。
heighti 是第 i 座建筑物的高度。
你可以假設所有的建筑都是完美的長方形,在高度為 0 的絕對平坦的表面上。
天際線 應該表示為由 “關鍵點” 組成的列表,格式 [[x1,y1],[x2,y2],…] ,并按 x 坐標 進行 排序 。關鍵點是水平線段的左端點。列表中最后一個點是最右側建筑物的終點,y 坐標始終為 0 ,僅用于標記天際線的終點。此外,任何兩個相鄰建筑物之間的地面都應被視為天際線輪廓的一部分。
注意:輸出天際線中不得有連續的相同高度的水平線。例如 […[2 3], [4 5], [7 5], [11 5], [12 7]…] 是不正確的答案;三條高度為 5 的線應該在最終輸出中合并為一個:[…[2 3], [4 5], [12 7], …]

示例 1:

輸入:buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
輸出:[[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
解釋:
圖 A 顯示輸入的所有建筑物的位置和高度,
圖 B 顯示由這些建筑物形成的天際線。圖 B 中的紅點表示輸出列表中的關鍵點。
示例 2:

輸入:buildings = [[0,2,3],[2,5,3]]
輸出:[[0,3],[5,0]]

提示:

1 <= buildings.length <= 104
0 <= lefti < righti <= 231 - 1
1 <= heighti <= 231 - 1
buildings 按 lefti 非遞減排序

懶刪除堆+ 掃描線

通過觀察示例,我們可以得出如下結論:
性質一:關鍵點的橫坐標一定是建筑的左右邊緣。令建筑的左右邊緣的集合是xs。
性質二:xs中除以下元素外,全部是關鍵點:
? \forall ?x,i ,其中 x ∈ \in xs。 x in $[lefti,righti] x對應的height 小于等于heighti。
性質三:根據性質二,一個x對應多個height,取最大值。xh記錄x及對應高度。
性質四:根據性質三,性質二可以簡化為 x in $(lefti,righti)
lh 記錄左邊界及高度。
rh記錄有邊界及高度。
xh、lh、rh都按x的升序排序。
有序mulset has代替懶刪除堆 記錄:
lefti < x ,righti > x的高度。 如果高度的最大值小于x對應的高度,則是關鍵點。

關鍵點的縱坐標y
{ 0 不存在 l e f t i 小于等于 x , r i g h t i 大于 x 的建筑 這些建筑的最大高度 o t h e r \begin{cases} 0 && 不存在lefti小于等于x,righti大于x的建筑\\ 這些建筑的最大高度 && other \\ \end{cases} {0這些建筑的最大高度??不存在lefti小于等于x,righti大于x的建筑other?
如果兩個相鄰的關鍵點高度相同,刪除前面的關鍵點。

代碼

核心代碼

  class Solution {public:vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {vector<pair<int, int>> tmp,xh, lh, rh;for (const auto& v : buildings) {lh.emplace_back(make_pair(v[0], v[2]));rh.emplace_back(make_pair(v[1], v[2]));}tmp = lh;tmp.insert(tmp.end(), rh.begin(), rh.end());sort(tmp.begin(), tmp.end());sort(rh.begin(), rh.end());		 for (const auto& [x, h] : tmp) {if (xh.size() && (xh.back().first == x)) {xh.back().second = h;}else {xh.emplace_back(make_pair(x, h));}}multiset<int> has;int il = 0, ir = 0;vector<vector<int>> ret;for (const auto& [x, h] : xh) {			 while ((il < lh.size() )&& (lh[il].first < x)) {has.emplace(lh[il++].second);}while ((ir < rh.size()) && (rh[ir].first <= x)) {has.erase(has.find(rh[ir].second));ir++;}if (has.empty() || (*has.rbegin() < h)) {ret.emplace_back(vector<int>{ x,-1 });}while ((il < lh.size()) && (lh[il].first <= x)) {has.emplace(lh[il++].second);}ret.back()[1] = has.empty()?0: *has.rbegin();	 }		vector < vector<int>> ret2 = { ret[0] };for (int i = 1; i < ret.size(); i++) {if (ret2.back()[1] != ret[i][1]) {ret2.emplace_back(ret[i]);}}return ret2;}};

單元測試

template<class T1, class T2>
void AssertEx(const T1& t1, const T2& t2)
{Assert::AreEqual(t1, t2);
}template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{Assert::AreEqual(v1.size(), v2.size());for (int i = 0; i < v1.size(); i++){Assert::AreEqual(v1[i], v2[i]);}
}template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{sort(vv1.begin(), vv1.end());sort(vv2.begin(), vv2.end());Assert::AreEqual(vv1.size(), vv2.size());for (int i = 0; i < vv1.size(); i++){AssertEx(vv1[i], vv2[i]);}
}namespace UnitTest
{	vector<vector<int>> buildings;TEST_CLASS(UnitTest){public:TEST_METHOD(TestMethod00){buildings = { {2,9,10},{3,7,15},{5,12,12},{15,20,10},{19,24,8} };auto res = Solution().getSkyline(buildings);AssertV2(vector<vector<int>>{ {2, 10}, { 3,15 }, { 7,12 }, { 12,0 }, { 15,10 }, { 20,8 }, { 24,0 }}, res);}TEST_METHOD(TestMethod01){buildings = { {0,2,3},{2,5,3} }		;auto res = Solution().getSkyline(buildings);AssertV2(vector<vector<int>>{ {0, 3}, { 5,0 }}, res);}};
}

簡化思路

所有x都是關鍵點,除非y和前一個x相同。
y = max(所有左邊界 <= x,右邊界大于x的建筑高度),所有沒有符合的建筑y為0。

class Solution {
public:vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {vector<pair<int, int>> tmp, xh, lh, rh;for (const auto& v : buildings) {lh.emplace_back(make_pair(v[0], v[2]));rh.emplace_back(make_pair(v[1], v[2]));}tmp = lh;tmp.insert(tmp.end(), rh.begin(), rh.end());sort(tmp.begin(), tmp.end());sort(rh.begin(), rh.end());for (const auto& [x, h] : tmp) {if (xh.size() && (xh.back().first == x)) {xh.back().second = h;}else {xh.emplace_back(make_pair(x, h));}}multiset<int> has;int il = 0, ir = 0;vector<vector<int>> ret;for (const auto& [x, h] : xh) {while ((il < lh.size()) && (lh[il].first <= x)) {has.emplace(lh[il++].second);}while ((ir < rh.size()) && (rh[ir].first <= x)) {has.erase(has.find(rh[ir].second));ir++;}int y = has.empty() ? 0 : *has.rbegin();if (ret.empty() || (ret.back()[1] != y)) {ret.emplace_back(vector<int>{x, y});}}return ret;}
};

擴展閱讀

視頻課程

先學簡單的課程,請移步CSDN學院,聽白銀講師(也就是鄙人)的講解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成戰斗了,為老板分憂,請學習C#入職培訓、C++入職培訓等課程
https://edu.csdn.net/lecturer/6176

相關推薦

我想對大家說的話
《喜缺全書算法冊》以原理、正確性證明、總結為主。
按類別查閱鄙人的算法文章,請點擊《算法與數據匯總》。
有效學習:明確的目標 及時的反饋 拉伸區(難度合適) 專注
聞缺陷則喜(喜缺)是一個美好的愿望,早發現問題,早修改問題,給老板節約錢。
子墨子言之:事無終始,無務多業。也就是我們常說的專業的人做專業的事。
如果程序是一條龍,那算法就是他的是睛

測試環境

操作系統:win7 開發環境: VS2019 C++17
或者 操作系統:win10 開發環境: VS2022 C++17
如無特殊說明,本算法用**C++**實現。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43871.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43871.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43871.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

景芯SoC訓練營DFT debug

景芯訓練營VIP學員在實踐課上遇到個DFT C1 violation&#xff0c;導致check_design_rule無法通過&#xff0c;具體報錯如下&#xff1a; 遇到這個問題第一反映一定是確認時鐘&#xff0c;于是小編讓學員去排查add_clock是否指定了時鐘&#xff0c;指定的時鐘位置是否正確。 景芯…

C語言文件操作-文件IO(系統調用)

文件IO (系統調用) 文件描述符open函數read函數write函數lseek函數close函數dup函數dup2函數 stat函數getpwuid函數getgrgid函數 實例 目錄操作 opendir函數readdir函數rewinddir函數closedir函數實例 文件IO (系統調用) 文件IO就是系統調用&#xff0c;用戶空間進入內核空間…

2024年信息系統項目管理師1批次上午客觀題參考答案及解析(3)

51、探索各種選項&#xff0c;權衡包括時間與成本、質量與成本、風險與進度、進度與質量等多種因素&#xff0c;在整個過程中&#xff0c;舍棄無效或次優的替代方案&#xff0c;這種不確定性應對方法是()。 A&#xff0e;集合設計 B&#xff0e;堅韌性 C&#xff0e;多種結果…

離線運行Llama3:本地部署終極指南_liama2 本地部署

4月18日&#xff0c;Meta在官方博客官宣了Llama3&#xff0c;標志著人工智能領域邁向了一個重要的飛躍。經過筆者的個人體驗&#xff0c;Llama3 8B效果已經超越GPT-3.5&#xff0c;最為重要的是&#xff0c;Llama3是開源的&#xff0c;我們可以自己部署&#xff01; 本文和大家…

衡量股票價值的尺度

勞倫女士說&#xff0c;“鄧普頓獵取便宜股的時候&#xff0c;總是運用證券分析師的‘一百種價值衡量尺度’中的好幾種。 原因之一呢&#xff0c;就是因為任何一種衡量方法都是萬能的&#xff0c;在不同的時期、不同的市場環境下&#xff0c;總會有它自己的局限性。就像有朋友…

大數據------JavaWeb------FilterListenerAJAXAxiosJSON

Filter Filter簡介 定義&#xff1a;Filter表示過濾器&#xff0c;是JavaWeb三大組件&#xff08;Servlet、Filter、Listener&#xff09;之一。 作用&#xff1a;它可把對資源&#xff08;Servlet、JSP、Html&#xff09;的請求攔截下來從而實現一些特殊功能 過濾器一般完成…

【QT中實現攝像頭播放、以及視頻錄制】

學習分享 1、效果圖2、camerathread.h3、camerathread.cpp4、mainwindow.h5、mainwindow.cpp6、main.cpp 1、效果圖 2、camerathread.h #ifndef CAMERATHREAD_H #define CAMERATHREAD_H#include <QObject> #include <QThread> #include <QDebug> #include &…

SAP顧問的核心競爭力是什么?

最近看到幾個業內大佬在討論這個話題&#xff0c;我也想談談我的看法。這位大佬的原話是“SAP顧問的核心技能不是配置軟件&#xff0c;而是對財務、供應鏈、銷售等運行流程的理解&#xff0c;解決的是企業流程和數據標準化的問題。” 我先不做評價&#xff0c;我先問幾個問題。…

選擇排序(C語言版)

選擇排序是一種簡單直觀的排序算法 算法實現 首先在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起始位置。 再從剩余未排序元素中繼續尋找最小&#xff08;大&#xff09;元素&#xff0c;然后放到已排序序列的末尾。 重復第二步&…

【k8s安裝redis】k8s安裝單機版redis實現高性能高可用

文章目錄 簡介一.條件及環境說明&#xff1a;二.需求說明&#xff1a;三.實現原理及說明四.詳細步驟4.1.創建configmap 配置文件4.2.創建StatefulSet 配置4.3.創建service headless 配置 五.安裝說明 簡介 本文將根據在k8s環境中搭建【偽】單機模式的redis實例。由于共享存儲的…

020-GeoGebra中級篇-幾何對象之點與向量

本文概述了在GeoGebra中如何使用笛卡爾或極坐標系輸入點和向量。用戶可以通過指令欄輸入數字和角度&#xff0c;使用工具或指令創建點和向量。在笛卡爾坐標系中&#xff0c;示例如“P(1,0)”&#xff1b;在極坐標系中&#xff0c;示例如“P(1;0)”或“v(5;90)”。文章還介紹了點…

深入理解循環神經網絡(RNN)

深入理解循環神經網絡&#xff08;RNN&#xff09; 循環神經網絡&#xff08;Recurrent Neural Network, RNN&#xff09;是一類專門處理序列數據的神經網絡&#xff0c;廣泛應用于自然語言處理、時間序列預測、語音識別等領域。本文將詳細解釋RNN的基本結構、工作原理以及其優…

uniapp本地打包到Android Studio生成APK文件

&#xff08;1&#xff09;安裝 Android Studio 軟件&#xff1b; 下載地址&#xff1a;官方下載地址&#xff0c;英文環境 安裝&#xff1a;如下之外&#xff0c;其他一鍵 next &#xff08;2&#xff09;配置java環境&#xff1b; 下載&#xff1a;j…

基于SpringBoot構造超簡易QQ郵件服務發送 第二版

目錄 追加 郵箱附件 添加依賴 編碼 測試 第二版的更新點是追加了 郵箱附件功能 ( 后期追加定時任務 ) 基于SpringBoot構造超簡易QQ郵件服務發送(分離-圖解-新手) 第一版 追加 郵箱附件 添加依賴 <!-- 電子郵件 --><dependency><groupId>org.spri…

Java小白入門到實戰應用教程-介紹篇

writer:eleven 介紹 編程語言介紹 編程語言按照抽象層次和硬件交互的方式劃分為低級編程語言和高級編程語言。 低級編程語言更接近計算機硬件層面&#xff0c;通常具有執行效率高的特點&#xff0c;但是由于注重計算機底層交互&#xff0c;所以編程難度相對較大。 高級編程…

國內開源RAG知識庫ChatWiki MaxKb QAnyThing對比

RAG 知識庫 &#xff0c; 是一個比較火的賽道&#xff0c;以下是國內開源的RAG 知識庫 ChatWiki 芝麻小客服開源的一個RAG 知識庫&#xff0c;核心特點是和人工聊天系統打通&#xff0c;可以作為對外的聊天系統使用。 開源地址 https://github.com/zhimaAi/chatwiki 云端體…

如何評價Flutter?

哈嘍&#xff0c;我是老劉 我們團隊使用Flutter已經快6年了。 有很多人問過我們對Flutter的評價。 今天在這里回顧一下6年前選擇Flutter時的原因&#xff0c;以及Flutter在這幾年中的實際表現如何。 選擇Flutter時的判斷 1、性能 最開始吸引我們的就是其優秀的性能。 特別是…

【vue3|第16期】初探Vue-Router與現代網頁路由

日期:2024年7月6日 作者:Commas 簽名:(? ?_?)? 積跬步以致千里,積小流以成江海…… 注釋:如果您覺得有所幫助,幫忙點個贊,也可以關注我,我們一起成長;如果有不對的地方,還望各位大佬不吝賜教,謝謝^ - ^ 1.01365 = 37.7834;0.99365 = 0.0255 1.02365 = 1377.4083…

力扣第226題“翻轉二叉樹”

在本篇文章中&#xff0c;我們將詳細解讀力扣第226題“翻轉二叉樹”。通過學習本篇文章&#xff0c;讀者將掌握如何使用遞歸和迭代的方法來翻轉二叉樹&#xff0c;并了解相關的復雜度分析和模擬面試問答。每種方法都將配以詳細的解釋&#xff0c;以便于理解。 問題描述 力扣第…

深入探索聯邦學習框架 Flower

聯邦學習框架 本文主要期望介紹一個設計良好的聯邦學習框架 Flower&#xff0c;在開始介紹 Flower 框架的細節前&#xff0c;先了解下聯邦學習框架的基礎知識。 作為一個聯邦學習框架&#xff0c;必然會包含對橫向聯邦學習的支持。橫向聯邦是指擁有類似數據的多方可以在不泄露…