Leetcode 239 Sliding Window Maximum

在这里插入图片描述
思路一: brute force,直接上代码:

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int count = nums.length - k + 1;
        int[] res = new int[count];
        for(int i = 0; i < count; i++){
            int max = Integer.MIN_VALUE;
            for(int j = i; j < i + k; j++){
                max = Math.max(max,nums[j]);
            }
            res[i] = max;
        }
        return res;
    }
}

思路二: 构建一个单调递减的deque,deque存放当前window的下标,这样deque的第一个元素就是当前window的答案。每次向右滑动的话,进行两个操作,remove last和(必要的话)remove first(因为deque的长度最长是k,但不一定会是k,可能小于k,小于的时候就不要remove first)。这两操作完了就在deque尾部加入下一个window的元素(addlast操作)。具体思路看下面这个链接:链接。下面直接上代码,代码上我也备注了很多注释:

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        
        // deque用来存放当前window下标,deque里面存的是index,但是index对应的值是单调递减的,这样就能保证deque的first element是最大的,就是当前window的最大值,也就是我们需要的答案
        Deque<Integer> deq = new ArrayDeque<>();
        
        // ans用来存放答案
        int[] ans = new int[nums.length - k + 1];
        
        // i用来追踪当前window的最后一个数的下标
        for(int i = 0; i < nums.length; i++){
            
            // 这个循环用来去除不可能是答案的那些下标,因为马上要新进来的数是i,i是要放在deque最末的,也就是要最小的,那么当前deque中比i小的都要去除,这样才能保证i加进去后是最小的
            while(!deq.isEmpty() && nums[i] > nums[deq.getLast()]){
                deq.removeLast();
            }
            
            // 因为上面removelast操作,所以导致deque长度可能是小于k的(去掉的那些都是不可能成为答案的数)。但deque最长的时候也可能是k,所以当deque长度为k时,这时候i要加进来,那么就必须把deque中的第一个element给删了,才能在尾巴加上i。除此之外,不用remove first
            if(!deq.isEmpty() && deq.getFirst() == i - k){
                deq.removeFirst();
            }
            
            // 在尾部加入新元素,此时i是最小的
            deq.addLast(i);
            
            // 只有当i至少走过k个元素后(产生第一个window),才会产出答案
            if(i - k + 1 >= 0){
                ans[i - k + 1] = nums[deq.getFirst()];
            }
        }
        return ans;
    }
}

总结:

  1. 碰到这种持续求最大最小值的题目可以考虑priority queue(heap),stack,deque之类的数据结构
  2. 这题我没有借此机会好好了解deque数据结构,只了解到可以双向插入数据,具体一些性质以及方法,复盘的时候要好好理解归纳。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值