力扣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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值