单调队列 | 滑动窗口 | 动态规划:力扣239. 滑动窗口最大值

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值