剑指offer第十六天-----滑动窗口的最大值

题目如下:

拿到手只想到了暴力解法,就是每次移动窗口,移动之后再查看一下当前窗口里的最大值。

时间复杂度较大,为O(n*k)  k为移动窗口大小。

代码如下:

class Solution {//参考牛客官方解答code
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> myret;
        if (num.size() == 0 || size < 1 || num.size() < size) return myret;
        //判断条件,当num的大小等于0或者滑动窗口的size小于1或者滑动窗口移动到数组最后面时
        //以上这些情况都会直接返回结果
        int n = num.size()
        for (int i = 0; i + size - 1 < n; ++i) {
            int j = i + size - 1;
            int max_val = num[j];
            for (int k = i; k < j; ++k) {
                max_val = max(max_val, num[k]);//在滑动窗口中进行判断最大值
            }
            myret.push_back(max_val);//保存最大值,循环完之后输出结果。
        }
        return myret;
    }
};

第二种方法就是觉得每次比较所有元素太啰嗦了

这个方法总的来说就是只让双端队列保存最大元素

import java.util.*;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size) {
        if (num == null || num.length == 0 || size <= 0 || num.length < size) {
            return new ArrayList<Integer>();
        }
        ArrayList<Integer> result = new ArrayList<>();
        //双端队列,用来记录每个窗口的最大值下标
        LinkedList<Integer> qmax = new LinkedList<>();
        
        for (int i = 0; i < num.length; i++) {  //这个for循环用来遍历每个点
            //这个循环用来比较当前遍历元素和之前所有元素,比当前元素小的就直接扔掉,不配当滑动窗口最大值
            while (!qmax.isEmpty() && num[qmax.peekLast()] < num[i]) {
                qmax.pollLast();           }
            qmax.addLast(i);    //每次必须加进去
            //判断队首元素是否过期  就是看这个元素是否被滑动窗口滑过去了
            if (qmax.peekFirst() <= i - size) {
                qmax.pollFirst();
            }
            //向result列表中加入元素  以上所有操作都做完说明当前队列队首的就是最大元素
            if (i >= size - 1) {    //只有当当前索引超过了滑动窗口大小才可以往里面塞东西
                result.add(num[qmax.peekFirst()]);
            }
        }
        return result;
    }
}

它用了一个双端队列,就是可以查看队列队首元素与队尾的一个数据结构。

首先是对每个元素的遍历循环:

  1.         在这个循环里,第一步就是查看刚才队列里的元素和当前元素作比较,做一个剔除操作(这个队列最大就只有size个元素,所以不用担心剔除的时候把什么重要的删掉)
  2.         之后就是将当前元素加入队列
  3.          查看一下队首元素是否过期了
  4.           将队首元素放入结果中 (注意只有遍历的节点索引超过了滑动窗口才可以放 不然放的都是没比较过的东西)

        就这个方法看起来挺聪明的,但是好像也就那样没啥卵用。时间复杂度还是不低。

但是并不是这样 因为维护单调队列的过程中是线性的遍历一遍元数组(就是那个剔除操作,剔除的时候只会看一遍那个元素,不可能遍历好多遍,因为那个元素要么太小被扔要么滑出去了,反正比较次数特别小),每个元素只被访问一次,故复杂度为O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值