LeetCode 🟡 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit
🔗 🟡 1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit 1672
tags: Weekly Contest 187
陣列(Array)
佇列(Queue)
滑動窗口(Sliding Window)
有序集合(Ordered Set)
堆積(Heap)
單調佇列(Monotonic Queue)
題意
給定一個整數陣列 和一個整數 ,請你返回最長連續子陣列的長度,該子陣列中的任意兩個元素之間的絕對差必須小於或者等於 。
如果不存在滿足條件的子陣列,則返回 。
思路:滑動窗口(Sliding Window)
這種連續子區間需滿足某些條件的問題,通常可以使用 滑動窗口(Sliding Window) 的技巧來解決。我們可以維護一個窗口,使得窗口內的最大值和最小值的差不超過 。當窗口內包含的子區間不再滿足條件時,我們縮小窗口的左邊界,直到條件再次滿足。
而維護窗口內的最大值和最小值,可以使用 有序集合(Ordered Set) 、堆積(Heap) 或者 單調佇列(Monotonic Queue) 來實現。
方法一:滑動窗口(Sliding Window) + 有序集合(Sorted Set)
使用一個 有序集合(Ordered Set) 來維護當前窗口內的所有元素。有序集合能夠讓我們快速獲取窗口內的最大值和最小值。
在本題中,我們需要維護窗口內的所有元素,因此需要使用有序的多重集合(multiset)。多重集合是一種集合,其中元素可以重複出現。在 Python
中,我們可以使用 sortedcontainers
提供的 SortedList
類別;在 C++
中,我們可以使用 multiset
。
具體步驟如下:
- 初始化左指針 以及答案 。
- 枚舉子陣列的右端點 :
a. 將當前元素加入有序集合。
b. 如果集合中最大值和最小值的差超過了 ,則移動左指針,並從集合中移除對應的元素,直到滿足條件。
c. 更新答案,取當前窗口大小和已知最大長度的較大值。 - 返回最終答案 即可。
複雜度分析
- 時間複雜度:,其中 是陣列的長度。
- 每次插入和刪除操作在有序集合中需要 的時間。
- 空間複雜度:,用於存儲有序集合中的元素。
1 | from sortedcontainers import SortedList |
1 | class Solution { |
方法二:滑動窗口(Sliding Window) + 單調佇列(Monotonic Queue)
由於我們只需要維護窗口內的最大值和最小值,而在當前窗口最大值左邊的值顯然不會再成為窗口內的最大值,因此在維護最大值時,我們可以將這些值從佇列中移除,換句話說,我們只需考慮 右側不存在更大值的元素 。同理,維護最小值時也是如此。故我們可以使用 單調佇列(Monotonic Queue) 來維護窗口內的最大值和最小值。
而在處理完兩個單調佇列後,我們只需檢查兩個佇列的首元素之差是否超過 ,如果超過 ,則需要移動左指針,並更新佇列。
具體步驟如下:
- 初始化兩個 雙端佇列(Deque) 和 ,分別用於維護窗口內的最小值和最大值。
- 初始化左指針 以及答案 。
- 枚舉子陣列的右端點 :
a. 更新 和 ,保持 的單調遞增性和 的單調遞減性。
b. 如果 的首元素減去 的首元素大於 ,則移動左指針,並更新佇列。
c. 更新答案,取當前窗口大小和已知最大長度的較大值。 - 返回最終答案 即可。
複雜度分析
- 時間複雜度:,其中 是陣列的長度。
- 每個元素最多被插入和刪除一次。
- 空間複雜度:,用於存儲兩個雙端佇列。
1 | class Solution: |
1 | class Solution { |
寫在最後
Cover photo is remixed from @吃肥皂泡泡, thanks for their work!