package main import ( "container/list" "fmt" ) func maxSlidingWindow(nums []int, k int) []int { if len(nums) == 0 { return []int{} } result := []int{} deq := list.New() for i := 0; i < len(nums); i++ { // Remove indexes out of the current window if deq.Len() > 0 && deq.Front().Value.(int) <= i-k { deq.Remove(deq.Front()) } // Remove smaller values at the end for deq.Len() > 0 && nums[deq.Back().Value.(int)] < nums[i] { deq.Remove(deq.Back()) } // Add current index deq.PushBack(i) // Append max to result if i >= k-1 { result = append(result, nums[deq.Front().Value.(int)]) } } return result } func main() { arr := []int{1,3,-1,-3,5,3,6,7} k := 3 fmt.Println(maxSlidingWindow(arr, k)) }
The sliding window maximum for the array with window size 3 is calculated by moving the window from left to right and picking the maximum in each window:
- Window [1,3,-1] max is 3
- Window [3,-1,-3] max is 3
- Window [-1,-3,5] max is 5
- Window [-3,5,3] max is 5
- Window [5,3,6] max is 6
- Window [3,6,7] max is 7
package main import ( "container/list" "fmt" ) func maxSlidingWindow(nums []int, k int) []int { if len(nums) == 0 { return []int{} } result := []int{} deq := list.New() for i := 0; i < len(nums); i++ { if deq.Len() > 0 && deq.Front().Value.(int) <= i-k { deq.Remove(deq.Front()) } for deq.Len() > 0 && nums[deq.Back().Value.(int)] < nums[i] { deq.Remove(deq.Back()) } deq.PushBack(i) if i >= k-1 { result = append(result, nums[deq.Front().Value.(int)]) } } return result } func main() { arr := []int{9,8,7,6,5,4,3,2,1} k := 4 fmt.Println(maxSlidingWindow(arr, k)) }
Since the array is strictly decreasing, the maximum in each window of size 4 is the first element of that window:
- [9,8,7,6] max is 9
- [8,7,6,5] max is 8
- [7,6,5,4] max is 7
- [6,5,4,3] max is 6
- [5,4,3,2] max is 5
- [4,3,2,1] max is 4
The condition deq.Front().Value.(int) < i-k is incorrect because it should be <= i-k to remove indexes that are out of the window. This causes old indexes to remain and incorrect maximum values.
A deque allows adding and removing elements from both ends in constant time. This helps keep indexes of elements that could be maximum in the current window, removing smaller elements from the back and old elements from the front efficiently.
package main import ( "container/list" "fmt" ) func countMaxElements(nums []int, k int) int { if len(nums) == 0 { return 0 } count := 0 deq := list.New() for i := 0; i < len(nums); i++ { if deq.Len() > 0 && deq.Front().Value.(int) <= i-k { deq.Remove(deq.Front()) } for deq.Len() > 0 && nums[deq.Back().Value.(int)] < nums[i] { deq.Remove(deq.Back()) } deq.PushBack(i) if i >= k-1 { count++ } } return count } func main() { arr := []int{2,1,3,4,6,3,8,9,10,12,56} k := 4 fmt.Println(countMaxElements(arr, k)) }
Each sliding window has exactly one maximum element. The number of sliding windows is (length of array - k + 1). For the given array of length 11 and k=4, number of windows = 11 - 4 + 1 = 8.
