力扣239,滑动窗口最大值

新人写文,出现错误还请各位大佬轻批

题目如下

方法一:简单易懂双循环,就不发了,自己写的还超时了
方法二:官方题解一,优先队列,在该方法中用到了堆(Java PriorityQueue - Java教程 - 菜鸟教程 (cainiaojc.com)),堆是完全二叉树可自动排序(时间复杂度NlogN)。思路很简单,先将前k个放入大根堆(既最大值为跟节点)里,堆顶就是最大值,堆会自动排序,随着模块移动,不断插入新元素,如果出现插入大于最大值则会自动插入到根节点,所以每次只用获取根节点即可,如果最大值不在模块里就把他扔出去,代码注释如下:
 public static int[] maxSlidingWindow(int[] nums, int k) {
        int n= nums.length;
        PriorityQueue<int[]> pq=new PriorityQueue<int[]>(new Comparator<int[]>() {
            @Override  //默认由小到大,本题需要由大到小
            public int compare(int[] o1, int[] o2) {
                return o1[0]!=o2[0]?o2[0]-o1[0]:o2[1]-o1[1];
            }
        });
        //将前k个数放入堆
        for (int i = 0; i < k; ++i) {
            pq.offer(new int[]{nums[i],i});
        }
        int[] ans=new int[n-k+1];
        ans[0]=pq.peek()[0];//获取前k个数的最大值
        for (int i = k; i < n; ++i) {
            pq.offer(new int[]{nums[i],i});
            while (pq.peek()[1]<=i-k){ //如果最大值已经不在滑动模块里,则将其移出堆
                pq.poll();
            }
            ans[i-k+1]=pq.peek()[0];//将堆里的最大值放入数组
        }
        return ans;
    }
方法三:单调队列

用到双向队列(Java Deque 接口 - Java教程 - 菜鸟教程 (cainiaojc.com)),队列中存的是从左往右单调递增的数的下标,如果不符合则将队列中的数一个个从后移出,直到符合,同时还要判断队列中的最大值既头元素的值是不是移出了移动模块,如果是则将头元素从头移出

int n= nums.length;
        Deque<Integer> deque=new LinkedList<>();
        for (int i = 0; i < k; ++i) {
            //队列里面会留下一个从左往右单调递增的数的下标,队首是最大值,队尾是最小值
            while (!deque.isEmpty() && nums[i]>=nums[deque.peekLast()]){
                deque.pollLast();
            }
            deque.offerLast(i);
        }
        int[] ans=new int[n-k+1];
        ans[0]=nums[deque.peekFirst()];//获取前k个数的最大值
        for (int i = k; i < n; ++i) {
            //模块开始移动,开始判断新进来的值是否符合队列
            while (!deque.isEmpty() && nums[i]>=nums[deque.peekLast()]){
                deque.pollLast();
            }
            deque.offerLast(i);
            //判断头元素是否还在移动模块中
            while (deque.peekFirst()<=i-k){
                deque.pollFirst();
            }
            ans[i-k+1]=nums[deque.peekFirst()];
        }
        return ans;
总结:本题思路并不难,都要遍历比较最大值,难点在于数据结构可以降低遍历时的时间复杂度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值