下面咱們經過幾個題目由淺入深,一點一點挖透他們吧!數組
提綱
app
請定義一個隊列並實現函數 max_value 獲得隊列裏的最大值ide
若隊列爲空,pop_front 和 max_value 須要返回 -1函數
示例 1:spa
輸入: ["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]設計
[[],[1],[2],[],[],[]] 3d
輸出: [null,null,null,2,1,2]code
示例 2:orm
輸入: 視頻
["MaxQueue","pop_front","max_value"]
[[],[],[]]
輸出: [null,-1,-1]
咱們先來拆解下上面的示例 1
其實我以爲這個題目的重點在理解題意上面,可能剛開始刷題的同窗,對題意理解不夠透徹,作起來沒有那麼駕輕就熟,經過上面的圖片咱們簡單瞭解了一下題意,那咱們應該怎麼作才能實現上述要求呢?
下面咱們來講一下雙端隊列。咱們以前說過的隊列,遵照先進先出的規則,雙端隊列則能夠從隊頭出隊,也能夠從隊尾出隊,不用遵照先進先出的規則,咱們先經過一個視頻來簡單瞭解下雙端隊列。
咱們能夠用雙端隊列作輔助隊列,用輔助隊列來保存當前隊列的最大值。咱們同時定義一個普通隊列和一個雙端單調隊列。普通隊列就正常執行入隊,出隊操做。max_value 操做則返回我們的雙端隊列的隊頭便可。下面咱們來看一下代碼的具體執行過程吧。
咱們來對視頻進行解析
1.咱們須要維護一個單調雙端隊列,上面的隊列則執行正常操做,下面的隊列隊頭元素則爲上面隊列的最大值
2.出隊時,咱們須要進行對比兩個隊列的隊頭元素是否相等,若是相等則同時出隊,則出隊後的雙端隊列的頭部仍爲上面隊列中的最大值。
3.入隊時,咱們須要維持一個單調遞減的雙端隊列,由於咱們須要確保隊頭元素爲最大值嘛。
給你一個整數數組 nums,有一個大小爲 k 的滑動窗口從數組的最左側移動到數組的最右側。你只能夠看到在滑動窗口內的 k 個數字。滑動窗口每次只向右移動一位。
返回滑動窗口中的最大值。
示例1:
輸入:nums = [1,3,-1,-3,5,3,6,7], k = 3 輸出:[3,3,5,5,6,7]
題目讓咱們找出每一個滑動窗口的最大值,那麼題目具體含義是怎樣呢?
就是爲了讓咱們輸出每一個窗口的最大值,那咱們思考一下,咱們一個數組一共有多少窗口呢?
好比咱們這個例子中,咱們的窗口長度爲 3 ,數組長度爲 8,咱們的窗口每次移動一位,因此咱們一共有 8 - (3 - 1)也就是 8 - 3 + 1。因此咱們返回數組的長度是跟原數組長度和滑動窗口的長度有關的。
也就是 winlen = len(數組長度) - k(滑動窗口長度) + 1。下面咱們來看一個視頻,相信經過這個視頻,你們一下就能搞懂啦。
1.先將咱們第一個窗口的全部值按照規則存入單調雙端隊列中,單調隊列裏面的值爲單調遞減的。若是發現隊尾元素小於要加入的元素,則將隊尾元素出隊,直到隊尾元素大於等於新元素時,再讓新元素入隊,目的就是維護一個單調遞減的隊列。第一個窗口的全部值入隊以後狀況,以下圖。是由於 3 要入隊時,此時隊中有 1 ,不能保證單調遞減,因此須要 1 出隊,而後 3 入隊, -1 入隊時,隊中有 3 ,知足單調,因此 -1 能夠入隊。
2.咱們將第一個窗口的全部值,按照單調隊列的規則入隊以後,由於隊列爲單調遞減,因此隊頭元素必爲當前窗口的最大值,則將隊頭元素添加到數組中。
3.移動窗口,判斷當前窗口前的元素是否和雙端隊列隊頭元素相等,若是相等則出隊,此時滑動窗口的最大值發生改變了。
4.繼續而後按照規則進行入隊,維護單調遞減隊列,這裏和第一條規則一致。
5.每次將隊頭元素存到返回數組裏。
6.返回數組
是否是一下就搞懂啦。你真帥,下面咱們來看一下代碼吧。
設計一個支持 push ,pop ,top 操做,並能在常數時間內檢索到最小元素的棧。
輸入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
輸出:
[null,null,null,null,-3,null,0,-2]
感受這個題目的難度就在讀懂題意上面,讀懂以後就沒有什麼難的了,咱們在上面的滑動窗口的最大值已經進行了詳細描述,其實這個題目和那個題目思路一致。
該題讓咱們設計一個棧,該棧具備的功能有,push,pop,top等操做,而且可以返回棧的最小值。好比此時棧中的元素爲 5,1,2,3。咱們執行 getMin() ,則可以返回 1。這塊是這個題目的精髓所在,見下圖, 這個題目也能夠不利用輔助棧解決,可是不符合本文主題,因此在這裏先不進行詳細描述。大體思路爲,把當前最小值用一個變量保存,須要入棧的值小於當前最小值時,先把當前最小值入棧,再將須要入棧的值入棧,並更新當前最小值。若是大於當前最小值,則直接入棧。getMin() 函數則直接返回變量保存的值便可。下面咱們來看一下咱們藉助輔助棧,如何解決這個題目吧。
1.咱們執行入棧操做時,先觀察須要入棧的元素是否小於棧 B 的棧頂元素,若是小於則兩個棧都執行入棧操做。
2.棧 B 的棧頂元素則是棧 A 此時的最小值。則 getMin() 只需返回棧 B 的棧頂元素便可。
3.出棧時,須要進行對比,若棧 A 和棧 B 棧頂元素相同,則同時出棧,出棧後B 的棧頂保存的仍爲此時棧 A 的最小元素
題目描述:
請根據每日 氣溫 列表,從新生成一個列表。對應位置的輸出爲:要想觀測到更高的氣溫,至少須要等待的天數。若是氣溫在這以後都不會升高,請在該位置用 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 大的數,也就是 31,31的下標爲 2,30 的下標爲 0 ,則咱們的返回數組 arr[0] = 2。理解了題目以後咱們來講一下解題思路。
遍歷數組,數組中的值爲待入棧元素,待入棧元素入棧時會先跟棧頂元素進行對比,若是小於等於該值則入棧,若是大於則將棧頂元素出棧,新的元素入棧。
例如棧頂爲69,新的元素爲72,則69出棧,72入棧。並賦值給 arr,69 的索引爲4,72的索引爲5,則 arr[4] = 5 - 4 = 1,這個題目用到的是單調棧的思想.
注:棧中的括號內的值,表明索引對應的元素,咱們的入棧的爲索引值,爲了便於理解將其對應的值寫在了括號中
這道接雨水也是一道特別經典的題目,一道必刷題目,咱們也用單調棧來解決。下面咱們來看一下題目吧
給定 n 個非負整數表示每一個寬度爲 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
看了上面的示例剛開始刷題的同窗可能有些懵逼,那咱們結合圖片來理解一下,咱們就用示例3的例子進行舉例,他的雨水到底表明的是什麼。輸入表明的是黃色箱子的個數,藍色箱子表明雨水數量。縫隙之間能夠裝多少水
上圖則爲咱們的題目描述,是否是理解了呢?你也能夠這樣理解咱們在地上放置了若干高度的黃色箱子,他們中間有空隙,而後咱們想在他們裏面插入若干藍色箱子,並保證插入以後,這些箱子的左視圖和右視圖都不能看到藍色箱子。
好啦題目咱們已經理解了,下面咱們來看一下接雨水問題到底該怎麼作,其實原理也很簡單,咱們經過咱們的例3來進行說明。
首先咱們依次入棧4,3,2,0咱們的數組前四個元素是符合單調棧規則的。可是咱們的第五個1,是大於0的。那咱們就須要0出棧1入棧。可是咱們這樣作是爲了什麼呢?有什麼意義呢?別急咱們來看下圖。
上圖咱們的,4,3,2,0已經入棧了,咱們的另外一個元素爲1,棧頂元素爲0,棧頂下的元素爲2。那麼咱們在這一層接到的雨水數量怎麼算呢?2,0,1這三個元素能夠接住的水爲一個單位(見下圖)這是咱們第一層接到水的數量。
注:能接到水的狀況,確定是中間低兩邊高的狀況
由於咱們須要維護一個單調棧,因此咱們則須要將0出棧1入棧,那麼此時棧內元素爲4,3,2,1。下一位元素爲1,咱們入棧,此時棧內元素爲4,3,2,1,1。下一元素爲5,棧頂元素爲1,棧頂的下一元素仍爲1,則須要再下一個元素,爲2,那咱們求當前層接到的水的數量。
注:棧內保存的應是索引值,這裏爲了便於理解用了value值
咱們是經過2,1,1,5這四個元素求得第二層的接水數爲1*3=3;1是由於min(2-1,5-1)=min(1,4)得來的,你們能夠思考一下木桶效應。裝水的多少,確定是按最短的那個木板來的,因此高度爲1,3的話是由於5的索引爲6,2的索引爲2,他們之間共有三個元素(3,4,5)也就是3個單位。因此爲6-2-1=3。將1出棧以後,咱們棧頂元素就變成了2,下一元素變成了3,那麼3,2,5這三個元素一樣也能夠接到水。
這是第三層的接水狀況,可以接到4個單位的水,下面咱們繼續出棧2,那麼咱們的4,3,5仍然能夠接到水啊。
這是咱們第四層接水的狀況,一共可以接到5個單位的水,那麼咱們總的接水數加起來,那就是1+3+4+5=13。你學會了嗎?別急還有動圖咱們,咱們再來深刻理解一哈。