剑指Offer(第2版)——面试题59:滑动窗口的最大值

题目

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

解题思路

  • 可以使用一个两端开口的队列(用STL中的deque来实现),用来保存有可能是滑动窗口最大值的数字的下标。
  • 接下来我们以数组{2,3,4,2,6,2,5,1}为例,来细说整体思路:
  • 数组的第一个数字是2,把它存入队列中。第二个数字是3,比2大,所以2不可能是滑动窗口中的最大值,因此把2从队列里删除,再把3存入队列中。第三个数字是4,比3大,同样的删3存4。此时滑动窗口中已经有3个数字,而它的最大值4位于队列的头部。
  • 第四个数字2比4小,但是当4滑出之后它还是有可能成为最大值的,所以我们把2存入队列的尾部(实时保留滑动窗口中位于队列头部值后面的第二大数字)。下一个数字是6,比4和2都大,删4和2,存6。就这样依次进行,最大值永远位于队列的头部。
    剑指Offer(第2版)——面试题59:滑动窗口的最大值_第1张图片

代码

class Solution{
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size){
        //储存每个滑动窗口的最大值
        vector<int> maxInWindows;
        // 数组大小要大于等于窗口大小,并且窗口大小大于等于1
        if(num.size() >= size && size >= 1){
        	//两端开口队列,储存数值的下标
            deque<int> index; 

            //窗口中数字的数量由0达到窗口大小数量
            for(unsigned int i = 0; i < size; i++){
                //更新队列头部最大值
                while(!index.empty() && num[i] >= num[index.back()]){
                    index.pop_back();
                }
                //压入滑动窗口中位于队列头部值后面的第二大数字
                index.push_back(i);
            }
            //压入队列头部最大值
            maxInWindows.push_back(num[index.front()]); 
            
            //窗口继续滑动
            for(unsigned int i = size; i < num.size(); i++){          
                while(!index.empty() && num[i] >= num[index.back()]){
                    index.pop_back();
                }
                //删除头部,保持窗口大小(要保证最大值下标大于i-size)
                if(!index.empty() && index.front() <= int(i - size)){
                	//弹出队列头数字
                    index.pop_front();
                }
                index.push_back(i);
                maxInWindows.push_back(num[index.front()]);
            }
        }
        return maxInWindows;
    }
};

你可能感兴趣的:(剑指Offer(第2版),栈队堆)