ALGORITHM SERIES | Generate an array of window maximums
Overview
Requirements
There is a integer array arr and a window of size w that slides from the leftmost to the rightmost part of the array, with the window sliding one position at a time to the right. For example, the array is [4,3,5,4,3,3,6,7], and the window size is 3.
If the length of the array is n and the window size is w, then a total of n-w+1 window maxima are generated. Please implement a function:
- Input: a integer array arr with window size w
- output: an array res of length n-w+1, res[i] denotes the maximum value in each window state, requiring time complexity O(N*w)
Solution
整体逻辑:
- 创建一个双端数组,我们需要根据不同情况从两端分别push和pop
- 核心就是循环这个arr,把最大的值在arr中的下标放到双端数组的最左端(对应下文程序中"for !bq.Empty() && arr[i] > arr[bq.Back().(int)] {}"的处理)
- 当窗口走过对应数值区域的时候,把相应的数据进行过期(对应下文程序中"if bq.Front().(int) == i-w {}")
- 注意,因为要输出长度为 n-w+1, 所以循环当"i >= w -1"的时候,才开始输出结果到res中
Overall logic:
- create a double-ended array, we need to push and pop from both ends according to different situations
- The core is to loop through the arr and put the largest value subscript in arr at the leftmost end of the double-ended array (corresponding to the following procedure "for !bq.Empty() && arr[i] > arr[bq. (int)] {}")
- expire the corresponding data when the window goes through the corresponding value area (corresponding to the following program "if bq.Front(). (int) == i-w {}")
- Note that since the length of the output is n-w+1, the loop starts when "i >= w -1" before outputting the result into res
Golang Implementation
1package main
2
3func Getmaxwindow(arr []int, w int) (res []int) {
4 res = []int{}
5 // 1. create a bidirectional queue to store the result
6 bq := newCustomQueue()
7 // 2. for i < length(arr)
8 for i := 0; i < len(arr); i++ {
9 // 3. for !empty or value(in queue) > value(in bqueue), popback bqueue
10 for !bq.Empty() && arr[i] > arr[bq.Back().(int)] {
11 bq.PopBack()
12 }
13 // 4. pushback id(in queue)
14 bq.Pushback(i)
15 // 5. if bqueue's id >= i - w, expire the front value(in bqueue)
16 if bq.Front().(int) == i-w {
17 bq.PopFront()
18 }
19 // 6. record results to res slice
20 if i >= w-1 {
21 res = append(res, arr[bq.Front().(int)])
22 }
23 }
24 return res
25}
Test Cases
1package main
2
3import (
4 "github.com/stretchr/testify/assert"
5 "testing"
6)
7
8func TestGetmaxwindow(t *testing.T) {
9 tests := []struct {
10 name string
11
12 arr []int
13 w int
14
15 wantRes []int
16 }{
17 {
18 name: "getmaxwindow",
19 arr: []int{4, 3, 5, 4, 3, 3, 6, 7},
20 w: 3,
21 wantRes: []int{5, 5, 5, 4, 6, 7},
22 },
23 {
24 name: "getmaxwindow1",
25 arr: []int{4, 3, 5, 4, 3, 3, 6, 7},
26 w: 4,
27 wantRes: []int{5, 5, 5, 6, 7},
28 },
29 {
30 name: "getmaxwindow2",
31 arr: []int{4, 3, 9, 8, 3, 1, 6, 7},
32 w: 3,
33 wantRes: []int{9, 9, 9, 8, 6, 7},
34 },
35 }
36 for _, tt := range tests {
37 t.Run(tt.name, func(t *testing.T) {
38 // test case
39 res := Getmaxwindow(tt.arr, tt.w)
40 assert.Equal(t, tt.wantRes, res)
41 })
42 }
43}
Result:
1$ go test -run ^TestSortStark$ . -v
2$ go test -run ^TestGetmaxwindow$ . -v
3=== RUN TestGetmaxwindow
4=== RUN TestGetmaxwindow/getmaxwindow
5=== RUN TestGetmaxwindow/getmaxwindow1
6=== RUN TestGetmaxwindow/getmaxwindow2
7--- PASS: TestGetmaxwindow (0.00s)
8 --- PASS: TestGetmaxwindow/getmaxwindow (0.00s)
9 --- PASS: TestGetmaxwindow/getmaxwindow1 (0.00s)
10 --- PASS: TestGetmaxwindow/getmaxwindow2 (0.00s)
11PASS
The test is problem-free and the output is as expected.