0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

深入淺出了解單調(diào)棧和單調(diào)隊列

Q4MP_gh_c472c21 ? 來源:袁廚的算法小屋 ? 作者:袁廚 ? 2021-02-02 10:18 ? 次閱讀

袁廚攜袁記菜館全體工作人員祝大家在新的一年,健健康康,開開心心。發(fā)量暴增,錢包超大。

哎,元旦假期結(jié)束了,又要繼續(xù)搬磚了,我們接著做題吧,今天我們好好說說單調(diào)棧和單調(diào)隊列。其實很容易理解,單調(diào)棧就是棧內(nèi)單調(diào)遞增或單調(diào)遞減的棧,棧內(nèi)元素是有序的,單調(diào)隊列同樣也是。

下面我們通過幾個題目由淺入深,一點一點挖透他們吧!

a5d57fd4-64cf-11eb-8b86-12bb97331649.png

提綱

單調(diào)隊列

劍指 Offer 59 - II. 隊列的最大值

題目描述:

請定義一個隊列并實現(xiàn)函數(shù) max_value 得到隊列里的最大值

若隊列為空,pop_front 和 max_value 需要返回 -1

示例 1:

輸入: ["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]

[[],[1],[2],[],[],[]]

輸出: [null,null,null,2,1,2]

示例 2:

輸入:

["MaxQueue","pop_front","max_value"]

[[],[],[]]

輸出: [null,-1,-1]

題目解析:

我們先來拆解下上面的示例 1

a615481c-64cf-11eb-8b86-12bb97331649.png

其實我覺得這個題目的重點在理解題意上面,可能剛開始刷題的同學(xué),對題意理解不夠透徹,做起來沒有那么得心應(yīng)手,通過上面的圖片我們簡單了解了一下題意,那我們應(yīng)該怎么做才能實現(xiàn)上述要求呢?

下面我們來說一下雙端隊列。我們之前說過的隊列,遵守先進(jìn)先出的規(guī)則,雙端隊列則可以從隊頭出隊,也可以從隊尾出隊,不用遵守先進(jìn)先出的規(guī)則,我們先通過一個視頻來簡單了解下雙端隊列。

我們可以用雙端隊列做輔助隊列,用輔助隊列來保存當(dāng)前隊列的最大值。我們同時定義一個普通隊列和一個雙端單調(diào)隊列。普通隊列就正常執(zhí)行入隊,出隊操作。max_value 操作則返回咱們的雙端隊列的隊頭即可。下面我們來看一下代碼的具體執(zhí)行過程吧。

我們來對視頻進(jìn)行解析

1.我們需要維護(hù)一個單調(diào)雙端隊列,上面的隊列則執(zhí)行正常操作,下面的隊列隊頭元素則為上面隊列的最大值

2.出隊時,我們需要進(jìn)行對比兩個隊列的隊頭元素是否相等,如果相等則同時出隊,則出隊后的雙端隊列的頭部仍為上面隊列中的最大值。

3.入隊時,我們需要維持一個單調(diào)遞減的雙端隊列,因為我們需要確保隊頭元素為最大值嘛。

題目代碼:

a67690cc-64cf-11eb-8b86-12bb97331649.png

239.滑動窗口最大值

題目描述:

給你一個整數(shù)數(shù)組 nums,有一個大小為 k 的滑動窗口從數(shù)組的最左側(cè)移動到數(shù)組的最右側(cè)。你只可以看到在滑動窗口內(nèi)的 k 個數(shù)字?;瑒哟翱诿看沃幌蛴乙苿右晃?。

返回滑動窗口中的最大值。

示例1:

輸入:nums = [1,3,-1,-3,5,3,6,7], k = 3 輸出:[3,3,5,5,6,7]

題目解析:

題目讓我們找出每個滑動窗口的最大值,那么題目具體含義是怎樣呢?

a6c42648-64cf-11eb-8b86-12bb97331649.png

就是為了讓我們輸出每個窗口的最大值,那我們思考一下,我們一個數(shù)組一共有多少窗口呢?

比如我們這個例子中,我們的窗口長度為 3 ,數(shù)組長度為 8,我們的窗口每次移動一位,所以我們一共有 8 - (3 - 1)也就是 8 - 3 + 1。所以我們返回數(shù)組的長度是跟原數(shù)組長度和滑動窗口的長度有關(guān)的。

也就是 winlen = len(數(shù)組長度) - k(滑動窗口長度) + 1。下面我們來看一個視頻,相信通過這個視頻,大家一下就能搞懂啦。

下面我們對視頻進(jìn)行拆解。

1.先將我們第一個窗口的所有值按照規(guī)則存入單調(diào)雙端隊列中,單調(diào)隊列里面的值為單調(diào)遞減的。如果發(fā)現(xiàn)隊尾元素小于要加入的元素,則將隊尾元素出隊,直到隊尾元素大于等于新元素時,再讓新元素入隊,目的就是維護(hù)一個單調(diào)遞減的隊列。第一個窗口的所有值入隊之后情況,如下圖。是因為 3 要入隊時,此時隊中有 1 ,不能保證單調(diào)遞減,所以需要 1 出隊,然后 3 入隊, -1 入隊時,隊中有 3 ,滿足單調(diào),所以 -1 可以入隊。

a706abf8-64cf-11eb-8b86-12bb97331649.png

2.我們將第一個窗口的所有值,按照單調(diào)隊列的規(guī)則入隊之后,因為隊列為單調(diào)遞減,所以隊頭元素必為當(dāng)前窗口的最大值,則將隊頭元素添加到數(shù)組中。

a7587316-64cf-11eb-8b86-12bb97331649.png

3.移動窗口,判斷當(dāng)前窗口前的元素是否和雙端隊列隊頭元素相等,如果相等則出隊,此時滑動窗口的最大值發(fā)生改變了。

a7aca5b2-64cf-11eb-8b86-12bb97331649.png

4.繼續(xù)然后按照規(guī)則進(jìn)行入隊,維護(hù)單調(diào)遞減隊列,這里和第一條規(guī)則一致。

5.每次將隊頭元素存到返回數(shù)組里。

6.返回數(shù)組

是不是一下就搞懂啦。你真帥,下面我們來看一下代碼吧。

題目代碼

a7e28f42-64cf-11eb-8b86-12bb97331649.png

單調(diào)棧

leetcode 155 最小棧

設(shè)計一個支持 push ,pop ,top 操作,并能在常數(shù)時間內(nèi)檢索到最小元素的棧。

push(x) —— 將元素 x 推入棧中。

pop() —— 刪除棧頂?shù)脑亍?/p>

top() —— 獲取棧頂元素。

getMin() —— 檢索棧中的最小元素。

輸入:

["MinStack","push","push","push","getMin","pop","top","getMin"]

[[],[-2],[0],[-3],[],[],[],[]]

輸出:

[null,null,null,null,-3,null,0,-2]

題目解析

感覺這個題目的難度就在讀懂題意上面,讀懂之后就沒有什么難的了,我們在上面的滑動窗口的最大值已經(jīng)進(jìn)行了詳細(xì)描述,其實這個題目和那個題目思路一致。

該題讓我們設(shè)計一個棧,該棧具有的功能有,push,pop,top等操作,并且能夠返回棧的最小值。比如此時棧中的元素為 5,1,2,3。我們執(zhí)行 getMin() ,則能夠返回 1。這塊是這個題目的精髓所在,見下圖, 這個題目也可以不利用輔助棧解決,但是不符合本文主題,所以在這里先不進(jìn)行詳細(xì)描述。大致思路為,把當(dāng)前最小值用一個變量保存,需要入棧的值小于當(dāng)前最小值時,先把當(dāng)前最小值入棧,再將需要入棧的值入棧,并更新當(dāng)前最小值。如果大于當(dāng)前最小值,則直接入棧。getMin()函數(shù)則直接返回變量保存的值即可。下面我們來看一下我們借助輔助棧,如何解決這個題目吧。

a83e070a-64cf-11eb-8b86-12bb97331649.png

我們一起先通過一個視頻先看一下具體解題思路,通過視頻一定可以整懂的,我們注意觀察棧 B 內(nèi)的元素。

我們來對視頻進(jìn)行解析

1.我們執(zhí)行入棧操作時,先觀察需要入棧的元素是否小于棧 B 的棧頂元素,如果小于則兩個棧都執(zhí)行入棧操作。

2.棧 B 的棧頂元素則是棧 A 此時的最小值。則 getMin() 只需返回棧 B 的棧頂元素即可。

3.出棧時,需要進(jìn)行對比,若棧 A 和棧 B 棧頂元素相同,則同時出棧,出棧后B 的棧頂保存的仍為此時棧 A 的最小元素

題目代碼

a877d566-64cf-11eb-8b86-12bb97331649.png

leetcode 739 每日溫度

題目描述:

請根據(jù)每日 氣溫 列表,重新生成一個列表。對應(yīng)位置的輸出為:要想觀測到更高的氣溫,至少需要等待的天數(shù)。如果氣溫在這之后都不會升高,請在該位置用 0 來代替。

示例1:

輸入:temperatures = [73, 74, 75, 71, 69, 72, 76, 73]

輸出:arr = [1, 1, 4, 2, 1, 1, 0, 0]

示例2:

輸入:temperatures = [30,30,31,45,31,34,56]

輸出:arr = [2,1,1,3,1,1,0]

題目解析

其實我們可以換種方式理解這個題目,比如我們 temperatures[0] = 30,則我們需要找到后面第一個比 30 大的數(shù),也就是 31,31的下標(biāo)為 2,30 的下標(biāo)為 0 ,則我們的返回數(shù)組 arr[0] = 2。理解了題目之后我們來說一下解題思路。

遍歷數(shù)組,數(shù)組中的值為待入棧元素,待入棧元素入棧時會先跟棧頂元素進(jìn)行對比,如果小于等于該值則入棧,如果大于則將棧頂元素出棧,新的元素入棧。

例如棧頂為69,新的元素為72,則69出棧,72入棧。并賦值給 arr,69 的索引為4,72的索引為5,則 arr[4] = 5 - 4 = 1,這個題目用到的是單調(diào)棧的思想,下面我們來看一下視頻解析。

注:棧中的括號內(nèi)的值,代表索引對應(yīng)的元素,我們的入棧的為索引值,為了便于理解將其對應(yīng)的值寫在了括號中

a8c1a42a-64cf-11eb-8b86-12bb97331649.png

leetcode 42 接雨水

這道接雨水也是一道特別經(jīng)典的題目,一道必刷題目,我們也用單調(diào)棧來解決。下面我們來看一下題目吧

題目描述:

給定 n 個非負(fù)整數(shù)表示每個寬度為 1 的柱子的高度圖,計算按此排列的柱子,下雨之后能接多少雨水。

示例1:

輸入:height =[0,1,0,2,1,0,1,3,2,1,2,1]

輸出:6

示例2:

輸入:height =[4,2,0,3,2,5]

輸出:9

示例2:

輸入:[4,3,2,0,1,1,5

輸出:13

題目解析:

看了上面的示例剛開始刷題的同學(xué)可能有些懵逼,那我們結(jié)合圖片來理解一下,我們就用示例3的例子進(jìn)行舉例,他的雨水到底代表的是什么。輸入代表的是黃色箱子的個數(shù),藍(lán)色箱子代表雨水?dāng)?shù)量。縫隙之間可以裝多少水

a90fa828-64cf-11eb-8b86-12bb97331649.png

說明:上面是由數(shù)組 [4,3,2,0,1,1,5]表示的高度圖,在這種情況下,可以接 13個單位的雨水(見下圖)。

上圖則為我們的題目描述,是不是理解了呢?你也可以這樣理解我們在地上放置了若干高度的黃色箱子,他們中間有空隙,然后我們想在他們里面插入若干藍(lán)色箱子,并保證插入之后,這些箱子的左視圖和右視圖都不能看到藍(lán)色箱子。 好啦題目我們已經(jīng)理解了,下面我們來看一下接雨水問題到底該怎么做,其實原理也很簡單,我們通過我們的例3來進(jìn)行說明。 首先我們依次入棧4,3,2,0我們的數(shù)組前四個元素是符合單調(diào)棧規(guī)則的。但是我們的第五個1,是大于0的。那我們就需要0出棧1入棧。但是我們這樣做是為了什么呢?有什么意義呢?別急我們來看下圖。

a9500dfa-64cf-11eb-8b86-12bb97331649.png

上圖我們的,4,3,2,0已經(jīng)入棧了,我們的另一個元素為1,棧頂元素為0,棧頂下的元素為2。那么我們在這一層接到的雨水?dāng)?shù)量怎么算呢?2,0,1這三個元素可以接住的水為一個單位(見下圖)這是我們第一層接到水的數(shù)量。 注:能接到水的情況,肯定是中間低兩邊高的情況

a9a1d252-64cf-11eb-8b86-12bb97331649.png

因為我們需要維護(hù)一個單調(diào)棧,所以我們則需要將0出棧1入棧,那么此時棧內(nèi)元素為4,3,2,1。下一位元素為1,我們?nèi)霔#藭r棧內(nèi)元素為4,3,2,1,1。 下一元素為5,棧頂元素為1,棧頂?shù)南乱辉厝詾?,則需要再下一個元素,為2,那我們求當(dāng)前層接到的水的數(shù)量。 注:棧內(nèi)保存的應(yīng)是索引值,這里為了便于理解用了value值

a9f9ee38-64cf-11eb-8b86-12bb97331649.png

我們是通過2,1,1,5這四個元素求得第二層的接水?dāng)?shù)為1*3=3;1是因為min(2-1,5-1)=min(1,4)得來的,大家可以思考一下木桶效應(yīng)。裝水的多少,肯定是按最短的那個木板來的,所以高度為1,3的話是因為5的索引為6,2的索引為2,他們之間共有三個元素(3,4,5)也就是3個單位。所以為6-2-1=3。 將1出棧之后,我們棧頂元素就變成了2,下一元素變成了3,那么3,2,5這三個元素同樣也可以接到水。

aa566686-64cf-11eb-8b86-12bb97331649.png

這是第三層的接水情況,能夠接到4個單位的水,下面我們繼續(xù)出棧2,那么我們的4,3,5仍然可以接到水啊。

aad0ff86-64cf-11eb-8b86-12bb97331649.png

這是我們第四層接水的情況,一共能夠接到5個單位的水,那么我們總的接水?dāng)?shù)加起來,那就是1+3+4+5=13。你學(xué)會了嗎?別急還有動圖我們,我們再來深入理解一哈。

題目代碼:

ab34aed2-64cf-11eb-8b86-12bb97331649.png

好啦,咱們的單調(diào)隊列和單調(diào)棧的題目到這里就算總結(jié)完畢啦,希望對你能有一點點幫助。

原文標(biāo)題:深入淺出搞通單調(diào)隊列單調(diào)棧

文章出處:【微信公眾號:嵌入式ARM】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴

原文標(biāo)題:深入淺出搞通單調(diào)隊列單調(diào)棧

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    嵌入式環(huán)形隊列與消息隊列的實現(xiàn)原理

    嵌入式環(huán)形隊列,也稱為環(huán)形緩沖區(qū)或循環(huán)隊列,是一種先進(jìn)先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),用于在固定大小的存儲區(qū)域中高效地存儲和訪問數(shù)據(jù)。其主要特點包括固定大小的數(shù)組和兩個指針(頭指針和尾指針),分別指向隊列的起始位置和結(jié)束位置。
    的頭像 發(fā)表于 09-02 15:29 ?293次閱讀

    深入淺出系列之代碼可讀性

    原創(chuàng)聲明:該文章是個人在項目中親歷后的經(jīng)驗總結(jié)和分享,如有搬運需求請注明出處。 這是“深入淺出系列”文章的第一篇,主要記錄和分享程序設(shè)計的一些思想和方法論,如果讀者覺得所有受用,還請“一鍵三連
    的頭像 發(fā)表于 08-09 16:00 ?221次閱讀

    深入淺出談TDR阻抗測試

    、脈寬、時序、抖動或噪聲內(nèi)容的任何事物都會影響整個系統(tǒng)的性能和可靠性。為保證信號完整性,必須了解和控制信號經(jīng)過的傳輸環(huán)境的阻抗。阻抗不匹配和不連續(xù)會導(dǎo)致反射,增加系
    的頭像 發(fā)表于 06-06 08:28 ?4873次閱讀
    <b class='flag-5'>深入淺出</b>談TDR阻抗測試

    深入淺出帶你搞懂-MOSFET柵極電阻

    一、MOSFET簡介MOSFET是金屬(metal)—氧化物(oxide)—半導(dǎo)體(semiconductor)場效應(yīng)晶體管,屬于電壓控制電流型元件,是開關(guān)電路中的基本元件,其柵極(G極)內(nèi)阻極高。以N溝道增強(qiáng)型為例,其結(jié)構(gòu)為在一塊濃度較低的P型硅上擴(kuò)散兩個濃度較高的N型區(qū)作為漏極和源極,半導(dǎo)體表面覆蓋二氧化硅絕緣層并引出一個電極作為柵極。由于mos管本身的
    的頭像 發(fā)表于 05-09 08:10 ?2.2w次閱讀
    <b class='flag-5'>深入淺出</b>帶你搞懂-MOSFET柵極電阻

    深入淺出帶你了解磁共振成像(MRI)基本原理

    磁共振成像技術(shù)原本稱為核磁共振成像。很多人聽到“核磁”,第1反應(yīng)是這個對人體有害嗎,因為名稱中不是有“核”嗎。其實,此處的”核“指”原子核“確實不假,但磁共振成像只與原子核的磁場相關(guān),與原子核聚變、裂變等的能量放射并無關(guān)系。因此,磁共振成像其實是利用人體組織中某種原子核的核磁共振現(xiàn)象,將所得射頻信號經(jīng)過計算機(jī)處理,重構(gòu)出人體某一層面的圖像的診斷技術(shù)。
    的頭像 發(fā)表于 04-03 17:04 ?837次閱讀
    <b class='flag-5'>深入淺出</b>帶你<b class='flag-5'>了解</b>磁共振成像(MRI)基本原理

    怎么理解負(fù)頻率呢?射頻人眼中的負(fù)頻率

    說實話,我對負(fù)頻率這個概念,也是有點凌亂。不過,最近不是正在看“深入淺出通信原理”嘛,看了一些相關(guān)概念。
    的頭像 發(fā)表于 03-05 16:10 ?2779次閱讀
    怎么理解負(fù)頻率呢?射頻人眼中的負(fù)頻率

    TC3xx的HSM中有沒有單調(diào)計數(shù)器?

    你好, 我看到 OPTIGA 有單調(diào)計數(shù)器,但我在 TC3xx 的 HSM 中確實找不到單調(diào)計數(shù)器。 能否確認(rèn)TC3xx的HSM中沒有單調(diào)計數(shù)器?
    發(fā)表于 03-05 07:56

    深入淺出理解三極管

    原文來自原創(chuàng)書籍《硬件設(shè)計指南 從器件認(rèn)知到手機(jī)基帶設(shè)計》: 本小節(jié)介紹下三極管的特性,清晰易懂,使用通俗的水流模型加強(qiáng)對三極管的原理記憶,一定比課堂上講的要形象的多,各位同學(xué)要學(xué)會類比的方法來加深記憶(比如在介紹相對論中引力扭曲時空的概念時,國外科學(xué)家們就用生活中的漩渦,或者在彈性膜中間的重球,來類比星體引力對時空的影響,這樣會大大簡化我們學(xué)習(xí)、理解和記憶的過程,這種學(xué)習(xí)方法被稱為類比學(xué)習(xí)法)。 我們
    的頭像 發(fā)表于 02-23 08:41 ?621次閱讀
    <b class='flag-5'>深入淺出</b>理解三極管

    深入淺出了解高邊驅(qū)動在汽車應(yīng)用中的挑戰(zhàn)

    隨著汽車電子技術(shù)發(fā)展,電動化,輕量化與智能化需求帶動了車規(guī)級高邊驅(qū)動(High-side Driver, HSD)在車身負(fù)載驅(qū)動中的大規(guī)模應(yīng)用。
    的頭像 發(fā)表于 01-23 10:05 ?5235次閱讀
    <b class='flag-5'>深入淺出了解</b>高邊驅(qū)動在汽車應(yīng)用中的挑戰(zhàn)

    【年度精選】2023年度top5榜單——電機(jī)控制資料

    推薦理由: 這是一份關(guān)于PID閉環(huán)控制算法的解析資料,內(nèi)容深入淺出,易于理解。通過這份資料,你可以全面了解PID控制算法的工作原理、參數(shù)調(diào)整技巧以及在實際應(yīng)用中的注意事項。無論你是初學(xué)者還是有一定經(jīng)驗
    發(fā)表于 01-16 14:34

    簡析控制系統(tǒng)的穩(wěn)定性判據(jù)

    上一篇視頻,我們已經(jīng)對控制系統(tǒng)分析的關(guān)鍵 —— 傳遞函數(shù)進(jìn)行了深入淺出的介紹(點我穿越回上一期內(nèi)容)。
    的頭像 發(fā)表于 01-03 12:37 ?2631次閱讀
    簡析控制系統(tǒng)的穩(wěn)定性判據(jù)

    深入了解 GaN 技術(shù)

    深入了解 GaN 技術(shù)
    的頭像 發(fā)表于 12-06 17:28 ?6033次閱讀
    <b class='flag-5'>深入了解</b> GaN 技術(shù)

    javascript深入淺出介紹

    JavaScript是一種廣泛使用的腳本語言,用于開發(fā)互聯(lián)網(wǎng)應(yīng)用程序。它非常受歡迎,因為它可以用于網(wǎng)頁開發(fā),服務(wù)器端開發(fā)以及移動應(yīng)用程序開發(fā)。本文將深入淺出地介紹JavaScript的各個方面,包括
    的頭像 發(fā)表于 12-03 11:09 ?5.7w次閱讀

    javascript深入淺出

    JavaScript是一種廣泛使用的編程語言,常用于Web開發(fā)。下面是對JavaScript的深入淺出的解釋: JavaScript簡介 JavaScript是一種解釋型、動態(tài)類型、基于原型的語言
    的頭像 發(fā)表于 11-16 10:34 ?2228次閱讀

    深入淺出了解華為云 API 網(wǎng)關(guān)的 Gzip 功能

    ? Gzip 是什么 Gzip 是一種用于數(shù)據(jù)壓縮的編碼格式,經(jīng)常被使用在基于 HTTP 協(xié)議的網(wǎng)絡(luò)傳輸中。Gzip 功能允許服務(wù)器在傳輸數(shù)據(jù)是對其進(jìn)行壓縮,從而減小傳輸?shù)臄?shù)據(jù)量,加快頁面加載速度,這對于節(jié)省帶寬和提高用戶體驗非常有用。本文將從 Gzip 使用場景、Gzip 原理、Gzip 在 nginx 中的應(yīng)用以及華為云 API?網(wǎng)關(guān)的 Gzip 功能實現(xiàn)幾個方面介紹 Gzip。 Gzip 使用場景 Gzip 能夠提升傳輸速度和降低帶寬消耗,因此適合應(yīng)用 Gzip 的場景有很多。 網(wǎng)頁傳輸:在 web 開發(fā)
    的頭像 發(fā)表于 11-12 17:36 ?382次閱讀
    <b class='flag-5'>深入淺出了解</b>華為云 API 網(wǎng)關(guān)的 Gzip 功能