题目描述:
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位,
返回滑动窗口中的最大值。
示例:
1) 输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置最大值
[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
2)输入:nums = [1], k = 1
输出:[1]
3)输入:nums = [1,-1], k = 1
输出:[1,-1]
4)输入:nums = [9,11], k = 2
输出:[11]
5)输入:nums = [4,-2], k = 2
输出:[4]
思路一:
每window大小的数据,进行一次堆排。
import heapq
# 这种方法会超时,而且空间复杂度较大,不断的去创建堆,相比于不断的维护堆所需要的时间更长
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
a = []
result = []
i = 0
while i < len(nums):
if i < k - 1:
a.append(-nums[i])
elif i == k - 1:
a.append(-nums[i])
temp = a.copy()
heapq.heapify(temp)
result.append(-temp[0])
else:
del a[0]
a.append(-nums[i])
temp = a.copy()
heapq.heapify(temp)
result.append(-temp[0])
i = i + 1
return result
时间复杂度过大,而且要不断的创建新的堆。
思路二:
利用优先队列,每滑入一个新的元素,就将元素加入到大顶堆中,每次在大顶堆中取最大的,若当前当前最大的在窗口的范围内,就取这个值,否则pop,直到堆顶是在窗口内的最大值。
import heapq
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
a = []
result = []
heapq.heapify(a)
i = 0
while i < len(nums):
heapq.heappush(a, (-nums[i], i)) # 构建大顶堆,这里要加上一个负号!
if i >= k - 1:
index = a[0][1]
while index < i - k + 1:
heapq.heappop(a)
index = a[0][1]
result.append(nums[index])
i = i + 1
return result
时间复杂度为O(nlogk)。
思路三:
用一个数组去完成比较任务,每次移动的时候,先把窗口最左边的也就是已经在左边被移出的去掉,然后比较即将进入的元素x与数组内的元素的大小,从数组的右侧开始,把小于x的都删掉,这样保证每次数组最大的值都是在窗口的最左边。这样的理由是,因为每次从右边开始删除,只要x进入数组,那数组内比x小的元素永远不会成为数组内最大的元素了,因为x在;从右侧开始比较的原因也是为了可以把数组最大的元素都放在最左边,不然可能出现这样的情况,6 4 ,即将进入的是5,我们应该把4删掉但是从6开始的话,就不会删掉了,无法在后面一直保证数组的最左边就是窗口的最大值。
import heapq
class Solution(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
if nums == []: return
window = [] # 存放下标
result = []
for i in range(len(nums)):
if i >= k and window[0] <= i - k:
window.pop(0)
x = nums[i]
while window and nums[window[-1]] <= x:
window.pop()
window.append(i)
if i >= k - 1:
result.append(nums[window[0]])
return result
时间复杂度为O(n), 这种方法可以减少时间复杂度,但是相对不是好想的。
注:
滑动窗口的题,是常考的,而且具有一定的难度,需要认真的对待。