單調隊列
用途
維持求解答案的可能性(包括 維持滑動窗口中的最大值或最小值)
核心原理
長江后浪推前浪——用最新最好的可能性淘汰最差最舊的可能性
in other words,討論可能性的價值與時效性
基本用法
分析可能性,若推出的可能性集合中有單調性
從隊頭和隊尾考慮沒有價值的可能性
錯題
LeetCode 1438. 絕對差不超過限制的最長連續子數組
錯誤想法:用了兩個隊列,分別維護最小值和最大值,檢查有無超過限制,若沒超過記錄答案,若超過比較兩者在num數組里的位置,將靠前的從隊頭出隊
錯因:這里很明顯把某些答案漏掉了
思路引領:觀察題目,這道題比較容易看出是找各種可能的題目,所以考慮可能性
從i開始,考慮以i為開頭的最長能擴到的子數組,這里可以發現,要滿足條件的話就要記錄這一段的最小值和最大值,且范圍擴大,最小值肯能更小,最大值可能更大,反之亦然。因此我們可以發現這個是有單調性的,進而想到滑動窗口這個邏輯
大體流程就是,r進來看能不能擴,如果能擴就擴,不能擴結算l這個位置的答案,然后將l從隊列里彈出(如果在頭部就彈出,不可能在尾部,因為它是最早的)
LeetCode 2071. 你可以安排的最多任務數目(這里隊列的單調性不是很明顯)
錯誤想法:沒思路,嘗試過每個工人完成離ta最近的任務,但又因為如果吃了藥這樣的話可能很浪費,所以不可行
思路引領:觀察題目,由于有藥片參與很難直接解決,但是發現“最多”,屬于最優化問題,加之我們可以判定任務數量的范圍,且具有單調性,check函數相對容易,所以進行二分答案
現在重點考慮check函數,(如果有m個任務,那么這么多藥片能否完成)
首先給task和worker排個序,那么check里面就是前m個任務和后m個工人,考慮工人i做的任務,要一下可能性
1)不用藥物可以滿足的
2)用藥物可以滿足的,那么做能做任務中消耗值最大的那個
3)用藥物也不滿足,false
這里會發現有指針回退的情況,為了避免,我們可以把能解鎖的任務都解鎖存在隊列里,如果x不能解鎖任務,從隊列里找,如果還不行,服用藥物找,那么就可以寫成
1)不用藥物,解鎖任務
2)不用藥物,從隊列里找出頭部做任務
3)服用藥物,解鎖任務,然后從隊列末尾找出要做的任務
4)服用藥物仍然不行,return false
算法:二分+貪心+單調隊列
總結
不要把隊列限制到值里面,隊列其實就是可能性的策略集合,只要可能性中存在單調性,就可以利用單調隊列
咳咳,要不要仔細校準一下,容易眼花QAQ,作者:江海一歸客,原文鏈接:http://www.rzrgm.cn/jhygk/p/19106067

浙公網安備 33010602011771號