1、题目描述:
困难题
2、题解:
方法1:单调队列
思路:
思路:
设置一个单调队列,队头到队尾,存放元素的下标,且对应元素的大小依次减小(对应的数组中的值依次减小),
也就是说队头必然对应该窗口的最大值的元素的下标。
算法步骤:
先处理特殊情况的结果
滑动指针right,
如果队列头部不在窗口范围内,就取出;
把nums[right]放到队列中(循环取出比它小的元素下标)
指针右移
如果right > k:添加窗口的最大值。
代码如下:
Python实现:
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
# #单调队列
res = []
import collections
queue = collections.deque()
if k == 0 or not nums:return res
right = 0
while right < len(nums):
if queue and queue[0] < right - k+1:
queue.popleft()
while queue and nums[right] > nums[queue[-1]]:
queue.pop()
queue.append(right)
right += 1
if right >= k:
res.append(nums[queue[0]])
return res
C++实现:
首先,介绍一下双端队列的使用:
class deque {
// 在队头插入元素 n
void push_front(int n);
// 在队尾插入元素 n
void push_back(int n);
// 在队头删除元素
void pop_front();
// 在队尾删除元素
void pop_back();
// 返回队头元素
int front();
// 返回队尾元素
int back();
}
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;
deque<int> queue;
for(int i= 0;i < nums.size();i++){
if (!queue.empty() && queue.front() < i - k +1){
queue.pop_front();
}
while (!queue.empty() && nums[i] > nums[queue.back()]){
queue.pop_back();
}
queue.push_back(i);
if (i >= k-1){
res.push_back(nums[queue.front()]);
}
}
return res;
}
};
方法2:滑动窗口
思路:
思路:
设置一个窗口,双指针,右指针向右滑动,当窗口的长度等于k时,开始移动窗口的左指针的长度,
每次在移动窗口左指针的时候,更新窗口内的元素的最大值
代码如下:
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
#滑动窗口法,超时
windows = []
left,right = 0,0
res = []
while right < len(nums):
c = s[right]
right += 1
windows.append(c)
while len(windows) == k:
res.append(max(windows))
left += 1
windows.pop(0)
return res
方法3:动态规划
思路:
先判断特殊情况
然后设置两个数组,left,right,分别存从左到右,每个值离当前窗口左端的最大值,
从右到左,每个值离当前窗口右端的最大值,
然后遍历,找 res.append(max(right[i],left[i+k-1]))
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
#动态规划
n = len(nums)
if n * k == 0:
return []
if k == 1:
return nums
left = [0] * n
right = [0] * n
left[0] = nums[0]
right[n-1] = nums[n-1]
for i in range(1,n):
if i % k == 0:
left[i] = nums[i]
else:
left[i] = max(left[i-1],nums[i])
j = n - i - 1
if (j + 1) % k == 0:
right[j] = nums[j]
else:
right[j] = max(right[j+1],nums[j])
res = []
for i in range(n-k+1):
res.append(max(right[i],left[i+k-1]))
return res
3、复杂度分析:
时间复杂度:O(N)
空间复杂度:O(N)