239.Sliding Window Maximum === ###### tags: `Hard` `Array` `Queue` `Sliding Window` `Heap` [239. Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/) ### 題目描述 You are given an array of integers `nums`, there is a sliding window of size `k` which is moving from the very left of the array to the very right. You can only see the `k` numbers in the window. Each time the sliding window moves right by one position. Return *the max sliding window.* ### 範例 **Example 1:** ``` Input: nums = [1,3,-1,-3,5,3,6,7], k = 3 Output: [3,3,5,5,6,7] Explanation: Window position Max --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7 ``` **Example 2:** ``` Input: nums = [1], k = 1 Output: [1] ``` **Constraints**: * 1 <= `nums.length` <= 10^5^ * -10^4^ <= `nums[i]` <= 10^4^ * 1 <= `k` <= `nums.length` ### 解答 #### TypeScript 思路: 1. 建立一個 deque 用來存放目前 window 範圍內的元素 index,並且 deque 中的索引值對應的元素值是降序排列。 2. 開始遍歷 nums,對目前元素 `nums[i]` 做以下處理: - 檢查 deque 中的第一個元素是否已經超出 window 範圍,如果是的話就將其移除。 - 從 deque 的尾部移除所有小於 `nums[i]` 的元素索引。這保證了 deque 中的索引值對應的元素值是降序排列。 - 將 `nums[i]` 的索引值放入 deque 的尾部。 - 如果 window 範圍內的元素個數已經達到 k 個,開始將 deque 中的第一個元素對應的元素值放入 result 中。 3. 回傳 result。 ```typescript function maxSlidingWindow(nums: number[], k: number): number[] { const result: number[] = []; const deque: number[] = []; for (let i = 0; i < nums.length; i++) { if (deque.length > 0 && deque[0] < i - k + 1) { deque.shift(); } while (deque.length > 0 && nums[deque[deque.length - 1]] < nums[i]) { deque.pop(); } deque.push(i); if (i >= k - 1) { result.push(nums[deque[0]]); } } return result; } ``` > [name=Sheep][time=Wed, 16 Aug 2023] #### C# ```csharp= public class Solution { public int[] MaxSlidingWindow(int[] nums, int k) { int[] ans = new int[nums.Length - k + 1]; var deque = new Deque(k); for (int i = 0; i < nums.Length; i++) { if (deque.PeekFirst() == i - k) { deque.RemoveFirst(); } while (!deque.IsEmpty() && nums[deque.PeekLast()] < nums[i]) { deque.RemoveLast(); } deque.AddLast(i); if (i - k + 1 >= 0) { ans[i - k + 1] = nums[deque.PeekFirst()]; } } return ans; } class Deque { private int[] deque; private int head, tail, size; public Deque(int size) { deque = new int[size]; } public bool IsEmpty() => size == 0; public int PeekFirst() => deque[head]; public int PeekLast() => deque[tail - 1 < 0 ? deque.Length - 1 : tail - 1]; public void AddLast(int value) { deque[tail] = value; MoveNext(ref tail); size++; } public void RemoveFirst() { MoveNext(ref head); size--; } public void RemoveLast() { MovePrevious(ref tail); size--; } private void MoveNext(ref int index) { index++; index = index == deque.Length ? 0 : index; } private void MovePrevious(ref int index) { index--; index = index < 0 ? deque.Length - 1 : index; } } } ``` > 原本用 heap 寫,但 heap 移除指定資料沒有比較快,看說明用 deque 就好 > C# 沒有 deque, 也可以用 LinkedList 替代,這邊寫一個堪用、不安全的 deque > [name=Jim][time=Aug 16, 2023] ### Reference [回到題目列表](https://marsgoat.github.io/XNnote/coding/leetcodeEveryDay.html)