239. 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
示例 2:
输入:nums = [1], k = 1
输出:[1]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
分析:看到每次向右移动一位,就可以想到先进先出的队列,但是呢我们又要找到一个大小为k窗口里面的最大元素,那么最暴力的方法就是再开一个for循环,去遍历寻找最大的元素,那么显然会超时。所以,我们应该考虑到使用优先队列,但是Golang中是没有现成的优先队列的,需要我们去手写一个大根堆。但是Golang提供了heap包,里面给了相应的接口,我们可以根据需要生成我们自己想要的数据结构,去实现大跟堆。
示例代码:
package queueimport ("container/heap"
)func maxSlidingWindow(nums []int, k int) []int {// 创建一个最大堆hp := &maxHeap{}// 第一次初始化堆heap.Init(hp)ans := make([]int, 0)// 处理前 k 个元素,构建初始堆for i := 0; i < k; i++ {heap.Push(hp, &element{value: nums[i], index: i})}// 第一个窗口的最大值ans = append(ans, (*hp)[0].value)// 滑动窗口n := len(nums)for i := k; i < n; i++ {// 将当前元素加入堆heap.Push(hp, &element{value: nums[i], index: i})// 删除堆中不在当前窗口内的元素for (*hp)[0].index <= i-k {heap.Pop(hp)}// 当前窗口的最大值ans = append(ans, (*hp)[0].value)}return ans
}// element 结构体,包含堆的元素值和索引
type element struct {value intindex int
}// maxHeap 实现最大堆,存储的类型是 *element
type maxHeap []*element// Len 堆的大小
func (h maxHeap) Len() int { return len(h) }// Less 比较堆中两个元素的大小,创建大根堆
func (h maxHeap) Less(i, j int) bool { return h[i].value > h[j].value }// Swap 交换堆中两个元素
func (h maxHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }// Push 向堆中插入一个元素
func (h *maxHeap) Push(x interface{}) {*h = append(*h, x.(*element))
}// Pop 弹出堆顶元素
func (h *maxHeap) Pop() interface{} {old := *hn := len(old)x := old[n-1]*h = old[0 : n-1]return x
}