🔴 862. Shortest Subarray with Sum at Least K
🔗 🔴 862. Shortest Subarray with Sum at Least K
Problem Statement
題目簡述
給定一個整數陣列 和一個整數 ,請找出 中和至少為 的最短非空子陣列的長度。
若不存在此類子陣列,則返回 。
Constraints
約束條件
思路:單調佇列與前綴和
轉換問題:前綴和
為了方便處理區間和,我們引入前綴和。
定義前綴和陣列 ,其中 ,且對於 :
這樣一來,任何一個子陣列 (其中 )的元素和,都可以表示為兩個前綴和之差:
則區間 的元素和至少為 的條件等價於:
問題等價於:尋找一對前綴和下標 ,滿足 ,使得 ,且 最小。
固定右端點 ,問題變成:在 的左側,尋找一個滿足 的最大下標 。
為什麼普通的滑動視窗(雙指標)會失效?
在 209. Minimum Size Subarray Sum 中,由於陣列中的元素均為正數,前綴和具有單調遞增的性質。這使我們可以用雙指標(滑動視窗)維護:當視窗內元素和至少為 時,我們可以直接收縮左邊界,因為更右邊的右邊界只會讓區間和更大,不用擔心漏掉答案。
然而,本題的元素可以為負數。這意味著前綴和不再具有單調性。即使我們增加左邊界,子陣列的和也可能因為移除了負數而變得更大;或者增加右邊界時,和反而因為加入了負數而變小。這使得滑動視窗的單調收縮邏輯徹底失效。
尋找優化:單調佇列的雙重篩選
既然 的暴力枚舉瓶頸在於保留了太多「無用」的左端點,我們如何一邊遍歷右端點 ,一邊高效篩選左端點 ?
我們可以用一個雙端佇列(Deque) 來維護候選的左端點下標。為了實現 的均攤複雜度,佇列需要進行雙向彈出優化:
關鍵觀察:左端點的雙重篩選機制
1. 隊尾彈出:剔除被支配的劣勢解(維護單調性)
假設佇列中已有兩個候選左端點 和 ,滿足 。
如果此時發現 ,那麼 將永遠不可能成為最優的左端點。
證明:為什麼 被 支配?
- 對於任何未來的右端點 ,如果 能與 配對(即 ),由於 ,我們必定也有 ,說明 也能與 配對。
- 由於 ,子陣列 的長度 必定比 的長度 更短。
- 因此,只要有 存在,在它左邊且前綴和更大的 就失去了存在的價值。我們可以直接將 從佇列尾部彈出。
- 操作:每次將當前前綴和 加入佇列前,從隊尾開始比較,將所有前綴和大於等於 的下標彈出。這保證了佇列中的前綴和是嚴格單調遞增的。
2. 隊首彈出:完成歷史使命的及時撤退(更新答案)
由於佇列內的前綴和是單調遞增的,隊首 是前綴和最小、最容易滿足配對條件的候選。
- 如果當前的右端點前綴和 滿足 ,那麼 就是一個候選的最短長度,我們更新全域最值。
證明:為什麼 可以永久彈出?
- 因為對於未來的任何右端點 ,即使 也能與 配對,其形成的子陣列長度 也必定大於 。
- 由於我們要求的是最短子陣列,未來的配對絕不可能刷新最短長度的紀錄。
- 操作:從隊首開始,只要滿足 ,就更新答案並將隊首彈出,直到不滿足條件為止。
核心套路:枚舉右,維護左
本題是「枚舉右端點,用單調佇列維護左端點」的經典模型。兩個方向的彈出各司其職:
- 隊尾彈出:剔除被支配的劣勢左端點,保證佇列單調遞增;
- 隊首彈出:完成配對即永久移除,避免重複計算。
每個下標至多入隊出隊一次,總時間複雜度優化至 。
複雜度分析
- 時間複雜度:。前綴和計算 ;遍歷過程每個下標至多入隊出隊各一次,均攤 。
- 空間複雜度:。
類題:
- 🟡 209. Minimum Size Subarray Sum - 全正數版本的本題,可以用雙指標維護,相對簡單許多
- 🟡 P1714 切蛋糕
- 🟡 3938. Maximum Path Intersection Sum in a Grid
Code
1 | class Solution: |
本部落格所有文章除特別聲明外,均採用CC BY-NC-SA 4.0 授權協議。轉載請註明來源 十六個天亮!
評論
WalineGiscus






