单调队列

来源:互联网 发布:长沙优化网站排名 编辑:程序博客网 时间:2024/06/06 04:47

单调队列指的是队列中的所有元素是单调递增或者单调递减的。

它可以在队首或队尾删除元素,只能在队尾插入元素,维护队列的均摊时间复杂度为O(1)。

单调队列一般用于解决的问题如,用一个长度为k的框在所给序列上移动,求框里面所包含的元素的最大值。

以单调递减队列为例:

队尾插入元素:为了保证队列的递减性,在插入元素num的时候,要将队尾元素和num比较,如果队尾元素不大于num,则删除队尾元素,然后继续将新的队尾元素与num比较,直到队尾元素大于num,这个时候我们才将num插到队尾。

队首删除元素:其实本质上我们只需要保存包括当前元素i在内的前k个元素中的最大值,所以当队首元素的下标小于i - k + 1的时候,就说明当前队首元素的存在已经没有意义了,要将队首元素删除。


核心代码(法一):

int n, k;  int a[100005],queue[100005];  void minQueue() {      int head = 1, tail = 0;      queue[head] = 1;      for (int i = 0; i < n; i++) {          //删除队首元素          if (i - queue[head] == k) head++;          //直接放在队尾          if (head - tail == 1 || a[i] > a[queue[tail]]) {//第一个条件指的是队列为空              queue[++tail] = i;          }          else {//不断删除队尾元素找到合适位置              while (tail >= head && a[i] <= a[queue[tail]]) {                  tail--;              }              queue[++tail] = i;          }          if (i >= k - 1) {              printf("%d%c", a[queue[head]], i == n - 1 ? '\n' : ' ');          }      }  }  void maxQueue() {      int head = 1, tail = 0;      queue[head] = 1;      for (int i = 0; i < n; i++) {          //删除队首元素          if (i - queue[head] == k) head++;          //直接放在队尾          if (head - tail == 1 || a[i] < a[queue[tail]]) {//第一个条件指的是队列为空              queue[++tail] = i;          }          else {//不断删除队尾元素找到合适位置              while (tail >= head && a[i] >= a[queue[tail]]) {                  tail--;              }              queue[++tail] = i;          }          if (i >= k - 1) {              printf("%d%c", a[queue[head]], i == n - 1 ? '\n' : ' ');          }      }  }  
核心代码(法二):

int n, k;  int a[100005];//原序列   int minQueue[100005],maxQueue[100005];//单调递减队列 单调递增队列  int minRe[100005],maxRe[100005];//结果   void solve() {      int minHead = 1, minTail = 0;//单调递减序列头、尾       int maxHead = 1, maxTail = 0;//单调递增序列头、尾       for (int i = 0; i < n; i++) {          //处理单调递减序列           while (minTail >= minHead && a[i] <= a[minQueue[minTail]]) {              minTail--;          }          minQueue[++minTail] = i;          if(i - minQueue[minHead] == k) minHead++;          //处理单调递增序列           while (maxTail >= maxHead && a[i] >= a[maxQueue[maxTail]]) {              maxTail--;          }          maxQueue[++maxTail] = i;          if(i - maxQueue[maxHead] == k) maxHead++;          //存储结果           if(i >= k - 1){              minRe[i] = a[minQueue[minHead]];              maxRe[i] = a[maxQueue[maxHead]];          }      }      //打印结果      for(int i = k - 1;i < n;i++){          printf("%d%c",minRe[i],i == n - 1?'\n':' ');      }      for(int i = k - 1;i < n;i++){          printf("%d%c",maxRe[i],i == n - 1?'\n':' ');      }   }  



原创粉丝点击