c++实现---滑动窗口的最大值

题目:
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。
方法一:暴力法
根据题目描述,我们很容易想到暴力方法。并且也很轻松的就可以写出来。
步骤如下:
枚举每个窗口的左边界 i
根据窗口的左边界i可以对应计算出右边界j
遍历窗口,计算出最大值
代码如下:

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> ret;
        if(num.size()==0||size<1||num.size()<size){//异常处理
            return ret;
        }
        int n=num.size();
        for(int i=0;i+size-1<n;++i){//i+size-1为滑动窗口最右端
            int j=i+size-1;
            int max_val=num[j];//默认每次取滑动窗最右端为最大值
            for(int k=i;k<j;++k){
                max_val=max(max_val,num[k]);
            }
            ret.push_back(max_val);//将所有最大的保存
        }
        return ret;
    }
};

时间复杂度:O(n*k), 其中n为数组大小,k为窗口大小
空间复杂度:O(1),存结果必须要开的数组不算入额外空间
方法一容易实现,但是时间复杂度可能难以满足面试要求,因此基于双端队列的优化解方法应该掌握。
方法二:双端队列
1遍历数组的每一个元素,
2如果容器为空,则直接将当前元素加入到容器中。
3如果容器不为空,则让当前元素和容器的最后一个元素比较,如果大于,则将容器的最后一个元素删除,然后继续讲当前元素和容器的最后一个元素比较
4如果当前元素小于容器的最后一个元素,则直接将当前元素加入到容器的末尾
5如果容器头部的元素已经不属于当前窗口的边界,则应该将头部元素删除
代码如下:

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> ret;
        if(num.size()==0||size<1||num.size()<size){//异常处理
            return ret;
        }
        int n=num.size();
        deque<int> dq;
        for(int i=0;i<n;++i){
            while(!dq.empty()&&num[dq.back()]<num[i]){//队列非空,并且队尾对应元素小于当前下标对应元素,则循环出队尾
                dq.pop_back();
            }
            dq.push_back(i);//将当前元素下标入队尾
            if(dq.front()+size<=i){//如果滑动窗口长度加上起始下标小于等于当前下标,窗口失效,则删除当前队首(最大的)元素
                dq.pop_front();
            }
            if(i+1>=size){//如果当前下标已经构成滑动窗口,则将队首元素保存
                ret.push_back(num[dq.front()]);
            }
        }
        return ret;
    }
};

时间复杂度:O(n), 其中n为数组大小
空间复杂度:O(k),k为窗口的大小

猜你喜欢

转载自blog.csdn.net/Fizz6018/article/details/107238128
今日推荐