力扣HOT100-滑动窗口最大值

思路

暴力解法: 对每个窗口,都单独遍历窗口内的最大值。 时间复杂度为O(nk)

优化解法:因为每次窗口的变化,仅涉及到一个元素出,一个元素入。因此,可以维护一个堆,通过操作堆,我们可以通过O(1)的复杂度获取当前窗口的最大值。

再次优化:对于一个堆而言,每次出入元素都需要调整堆,但很多时候的调整是没必要的。

我们思考这样一种情况,如果当前窗口有两个下标i,j,且i<j,同时nums[i] <= nums[j]。那么堆中记录nums[i]是毫无意义的。因为滑动窗口向右移动,i在窗口时,j也一定在窗口,所以我们就可以将nums[i]移除。

因此我们可以使用一个队列存储所有还没有被移除的下标。在队列中,这些下标按照从小到大的顺序被存储,并且它们在数组 nums 中对应的值是严格单调递减的。

Python版本

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        res = []
        # 双端队列
        q = deque()
        n = len(nums)
        for i in range(n):
            # 当前元素是否能加入到单调队列的末尾
            while q and nums[q[-1]] < nums[i]:
                q.pop()
            q.append(i)
            # 判断当前队首元素是否在窗口内
            if i - q[0] >= k:
                # 移除队首
                q.popleft()
            if i >= k - 1:
                res.append(nums[q[0]])
        return res

Java版本

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        int[] ans = new int[n-k+1];
        Deque<Integer> q = new ArrayDeque();
        for (int i = 0;i<n;i++){
            while (!q.isEmpty() && nums[q.getLast()] < nums[i]){
                q.removeLast();
            }
            q.addLast(i);
            if (i - q.getFirst() >= k){
                q.removeFirst();
            }
            if (i >= k - 1){
                ans[i-k+1] = nums[q.getFirst()];
            }
        }
        return ans;
    }
}
### 关于滑动窗口最大值问题的解法 对于给定的一个整数数组 `nums` 和一个大小为 `k` 的滑动窗口,目标是从左至右遍历该数组并记录每一个滑动窗口中的最大值。一种直观的方法是通过暴力求解来获取每个窗口的最大值,然而这种方法的时间复杂度较高,达到 O((n - k + 1) * k)[^1]。 为了提高效率,可以采用更优的数据结构——单调队列来进行处理。单调队列是一种特殊的双端队列,在这里用于存储当前窗口内元素下标的集合,并保持这些下标对应的数值按降序排列[^4]。具体来说: - 当新元素进入窗口时,移除队列中所有小于等于它的元素(因为它们不可能成为后续任何窗口的最大值),再将新的元素加入到队尾; - 如果队首元素已经不在当前窗口范围内,则将其弹出; - 此时队首即为当前窗口的最大值所在位置; 下面给出基于上述逻辑的具体 Python 实现方式: ```python from collections import deque def maxSlidingWindow(nums, k): result = [] window = deque() for i in range(len(nums)): # 移除不在当前窗口范围内的索引 if window and window[0] <= i - k: window.popleft() # 维护单调递减性质 while window and nums[i] >= nums[window[-1]]: window.pop() window.append(i) # 记录结果 if i >= k - 1: result.append(nums[window[0]]) return result ``` 此算法能够在线性时间内完成计算,时间复杂度降低到了 O(n),极大地提高了程序运行效率[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值