剑指offer - 滑动窗口最大值 (单调队列的使用)& POJ 2823

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。

牛客网上剑指offer的题目(书上似乎没这个题?)

题意很简单,给你一个长度为N的数组,对于(0,N-K+1)范围的每个数,求出i-i+K-1范围内的最大值。
最开始想到的是RMQ查询或者线段树,但感觉这种做法很傻逼,应该不是剑指offer的做法。后来看了下,用单调的双向队列即可。就是维护一个双向的队列,队列里面是有序的,对于当前i,如果从队列尾部开始查到适合i插入的位置,并把后面的数全部删除。
代码如下:

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int> res;
        if(size <= 0 || num.size() == 0)    return res;
        deque<int> d;
        for(int i=0;i<num.size();++i){
            while(d.size() > 0 && num[d.back()] <= num[i]){
                d.pop_back();
            }
            d.push_back(i);
            if(i +1 >= size){
                res.push_back(num[d.front()]);
                if(d.front() == i+1-size)
                    d.pop_front();
            }
        }
        return res;
    }
};

//这里在G++下会超时,C++可以通过,应该是G++对STL的优化不太好。
POJ 2823 题目基本相似,不过是要求最大值和最小值,所以需要维护两个双端队列
代码如下:

#include<iostream>
#include<string>
#include<algorithm>
#include<cmath>
#include<deque>
#include<cstdio>
using namespace std;
const int MAX = 1e6+10;
int a[MAX],N,K;
deque<int> Max,Min;
int Maxvalue[MAX],Minvalue[MAX];
void solve(){
    for(int i=1;i<=N;++i){
        while(!Max.empty() && a[Max.back()] < a[i])
            Max.pop_back();
        Max.push_back(i);
 //       printf("MaxD = %d\n",Max.v[Max.s]);
        while(!Min.empty() && a[Min.back()] > a[i])
            Min.pop_back();
        Min.push_back(i);
        if(i - K +1 > 0){
            Maxvalue[i-K+1] = a[Max.front()];
            Minvalue[i-K+1] = a[Min.front()];
            if(Min.front() == i-K+1)
                Min.pop_front();
            if(Max.front() == i-K+1)
                Max.pop_front();
        }
    }
    for(int i=1;i<=N-K+1;++i){
        printf("%d%c",Minvalue[i],i==N-K+1?'\n':' ');
    }
    for(int i=1;i<=N-K+1;++i){
        printf("%d%c",Maxvalue[i],i==N-K+1?'\n':' ');
    }
}
//#define test
int main(void){
    #ifdef test
        freopen("in.txt","r",stdin);
    #endif // test
    while(scanf("%d%d",&N,&K) != EOF){
        for(int i=1;i<=N;++i){
            scanf("%d",&a[i]);
        }
        solve();
    }
    #ifdef test
        fclose(stdin);
    #endif // test

    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章