我们常常会用循环的方法来解决这个问题,但是不幸的是这样做却往往会超时,因为这样的时间复杂度太高了,代码如下:
n = len(nums)
if n == 0:
return []
ans = []
temp = max(nums[:k])
for i in range(n-k):
ans.append(temp)
if nums[i+k] > temp:
temp = nums[i+k]
else:
if nums[i] == temp:
temp = max(nums[i+1:i+1+k])
ans.append(temp)
return ans
这里就是简化的暴力求解,我们分析以下时间复杂度。要循环n-k次,每次都要找出来比较,这里的复杂度是O((n-k)*n),可以认为是O(n**2)这里的复杂度已经不是线性的,我们来分析一下双端队列。
双端队列解法代码如下:
deque = collections.deque()
ans = []
for i, num in enumerate(nums):
if deque and deque[0] <= i-k:
deque.popleft()
while deque and nums[deque[-1]] < num:
deque.pop()
deque.append(i)
if i >= k-1:
ans.append(nums[deque[0]])
return ans
这里我们双端队列里储存的是值的下标,我们在第一个位置保存为最大值,如果移动时左边超过了极限,那么我们就删去左边的一个,如果最后一个加入的元素没有下面循环的大,那么我们就可删除最后,加入新的元素,如果我们加入的元素已经到达了滑动窗口的长度,那么我们就可以取值了。
我们分析时间复杂度,双端队列的取值和加入都是O(1),循环时O(n),所以时间复杂度只有O(n),是线性的复杂度。