【deque】滑动窗口、双端队列解决数组问题

C++手册之deque

所属头文件 <deque>

常用操作: 

back()返回尾部元素;

front()返回头部元素;

push_back()尾部插入元素;

pop_bakc()尾部删除元素;

push_front()头部插入元素;

pop_front()头部删除元素;


问题1:求滑动窗口的最大值(《剑指offer面试题65》)

描述:给定一个数组和滑动窗口的大小,找出所有滑动窗口里的最大值。

示例:数组{2, 3, 4, 2, 6, 2, 5} 窗口大小为 3,一共有7-3+1=5个滑动窗口,返回这些窗口最大值的数组{4, 4, 6, 6, 6}

方法:生成一个双端队列deque,里面存储可能成为滑动窗口最大值在数组中的下标

vector<int> getMax(const vector<int> &arr, int size){
    vector<int> res;
    if (arr.size() == 0 || size <= 0){
        return res;
    }
    deque<int> index;
    int i = 0;
    while (i < arr.size()){
        while (!index.empty() && arr[index.back()] <= arr[i]){
            index.pop_back();
        }
        index.push_back(i);
        if (!index.empty() && index.front() == (i - size)){
            index.pop_front();//不属于当前窗口
        }
        if (i >= size - 1){
            res.push_back(arr[index.front()]);
        }
        i++;
    }
    return res;
}

问题2:给定一个数组,找出最大值与最小值之差小于等于给定数num的子数组的个数。(牛客左程云《程序员面试代码指南》)

示例:给定数组{5, 2, 6, 3, 4, 1},num = 3,符合条件的子数组分别为{5} {5, 2} {2} {6} {6, 3} {6, 3, 4} {3} {3, 4} {3, 4, 1} {4} {4, 1} {1}返回数值12

方法:生成两个双端队列qmax, qmin,第一层while循环i,满足条件的将i作为起始元素的子数组;第二层while循环,满足条件的将j作为尾元素的子数组。每次内while循环结束,结果res += j - i;

qmax维护窗口子数组最大值在原数组中的下标;

qmin维护窗口子数组最小值在原数组中的下标。

窗口在动态发生变化,qmax和qmin的元素也在发生变化。

 1 int getNum(int arr[], int len, int num){
 2     if (arr == NULL || len < 1 ||num < 0)
 3         return 0;
 4     int res = 0;
 5     deque<int> qmax;
 6     deque<int> qmin;
 7     int i = 0;
 8     int j = 0;
 9     while (i < len){
10         while (j < len){
11             while (!qmax.empty() && arr[qmax.back()] <= arr[j]){
12                 qmax.pop_back();
13             }
14             qmax.push_back(j);
15             while (!qmin.empty() && arr[qmin.back()] >= arr[j]){
16                 qmin.pop_back();
17             }
18             qmin.push_back(j);
19             if (arr[qmax.front()] - arr[qmin.front()] > num){
20                 break;
21             }
22             j++; //j一直在变大,不回退
23         }
24         if (qmax.front() == i){
25             qmax.pop_front(); //不属于以i+1开头的窗口,弹出
26         }
27         if (qmin.front() == i){
28             qmin.pop_front(); //不属于以i+1开头的窗口,弹出
29         }
30         res += j - i;
31         i++; //i一直在变大,不回退
32     }
33     return res;
34 }
原文地址:https://www.cnblogs.com/cnblogsnearby/p/4767061.html