具体请参见代码中的注释,主要逻辑为维护一个单调递减的双端队列,从0开始遍历数组,若当前元素的值大于双端队列的某个值,将该值往后的所有值全部出队(因为单调递减,后面所有值都小于当前元素),再将当前元素入队,然后取队首作为当前窗口的最大值。(遍历过程中需要注意队首元素的下标不能超过窗口的size,否则队首最大值过期,将队首元素出队)
func maxInWindows(num []int, size int) []int { // write code here if len(num) <= 1 || size <= 1 { return num } res := []int{} deque := [][2]int{} //单调双端队列 第一维为保存的元素值 第二维为数组下标,方便检查队头最大值是否越界(窗口) deque = append(deque, [2]int{num[0], 0}) // 首个元素入队 for i := 1; i < size; i++ { // 窗口初填满,找到最大值(deque队首元素) index := findFirstSmallIndex(deque, num[i]) // deque单调递减,index为deque中第一个元素值小于num[i]的位置 deque = deque[:index] // 去掉index后的所有元素 deque = append(deque, [2]int{num[i], i}) // 之后插入num[i] } // 将队首元素加入结果集 res = append(res, deque[0][0]) right := size for right < len(num) { if right-deque[0][1] >= size { // 如果右指针-队首元素的下标超过size,说明窗口无法容纳队首元素,需去除 deque = deque[1:] continue } index := findFirstSmallIndex(deque, num[right]) // 类似窗口初填满时的逻辑 deque = deque[:index] // 去掉队列中后续较小元素 deque = append(deque, [2]int{num[right], right}) //去掉后队尾插入元素 res = append(res, deque[0][0]) //队首元素加入结果集 right++ } return res } func findFirstSmallIndex(num [][2]int, target int) int { for i := 0; i < len(num); i++ { if num[i][0] <= target { return i } } return len(num) }