剑指Offer60--面试题59 - I. 滑动窗口的最大值

剑指Offer60--面试题59 - I. 滑动窗口的最大值

题目描述

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

代码

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
         ArrayList<Integer> res = new  ArrayList<Integer>();
         if(size==0) return res;
        int i=0,j=size-1;
        while(j<num.length){
            int max = Integer.MIN_VALUE;
            for(int k=i;k<=j;k++){
                if(max<=num[k]){
                   max = num[k];
                }
            }
            res.add(max);
            i++;
            j++;
        }
        
        return res;
    }
}

优化

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
        ArrayList<Integer> res = new  ArrayList<Integer>();
        if(size==0||num.length<size) return res;
        int i=0,j=size-1;
        int max=num[0];
        int maxIdx = 0;
        // 首先找出第一个滑窗的最大值,并且取得索引
        for(int k=1; k<=j; k++){
            if(max<=num[k]){
                max=num[k];
                maxIdx = k;
            }
        }
        res.add(max);
        //移动到第二个滑动窗口
        i=i+1;
        j=j+1;
        while(j<num.length){
            // 如果上一个滑动窗的最大值,不在这个滑动窗中
            if(i>maxIdx){
                maxIdx = i;
                max = num[i];
                for(int m=i+1;m<=j;m++){
                    if(num[m]>=max){
                        max = num[m];
                        maxIdx = m;
                    }
                }
            }else{// 如果上一个滑动窗的最大值,在这个滑动窗中
                if(num[j]>=max){
                    max = num[j];
                    maxIdx = j;
                }
            }
            
            res.add(max);
            i++;
            j++;
        }
        
        return res;
    }
}

单调双向队列

学习参考链接

 if (nums == null || k < 1 || nums.length < k) {
            return new int[0];
        }

        int index = 0;
        int[] res = new int[nums.length - k + 1];
        LinkedList<Integer> queue = new LinkedList<>();

        for (int i = 0; i < nums.length; i++) {
            // 在队列不为空的情况下,如果队列尾部的元素要比当前的元素小,或等于当前的元素
            // 那么为了维持从大到小的原则,我必须让尾部元素弹出
            while (!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]) {
                queue.pollLast();
            }
            // 不走 while 的话,说明我们正常在队列尾部添加元素
            queue.addLast(i);
            // 如果滑动窗口已经略过了队列中头部的元素,则将头部元素弹出
            if (queue.peekFirst() == (i - k)) {
                queue.pollFirst();
            }
            // 看看窗口有没有形成,只有形成了大小为 k 的窗口,我才能收集窗口内的最大值
            if (i >= (k - 1)) {
                res[index++] = nums[queue.peekFirst()];
            }
        }
        return res;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值