要求实现一个队列或栈,并且在O(1)的时间内,完成pop()、push()和max()的操作。
1 最大值队列
《剑指Offer》面试题59
用一个正常的队列实现数据的插入和删除,满足FIFO的关系。用一个双向队列保存当前队列中的最大值,并且保证当前最大值始终位于双向队列的前端。如何维护这个双向队列呢?
新数据插入时,将双向队列后部所有比新数据小的元素删除,因为这些元素不可能是未来的最大值了。再将新数据插入到双向队列的后部。
数据删除时,判断双向队列前部的数据的下标是否等于或小于删除数据的下标(实际上只能等于),如果等于则将双向队列的前部数据删除。这就是为何保持最大值应当使用双向队列,以及为何一定要使得数据中有下标的属性。
#include <iostream>
#include <queue>
#include <deque>
#include <stdexcept>// logic_error头文件
#include <exception>// exception头文件
using namespace std;
template<typename T>
class QueueWithMax{
private:
// index在判断最大值是否被pop时需要
struct InternalData {
T num;
int index;
};
// 存储原始数据的队列
queue<InternalData> data;
// 存储最大值以及可能最大值的双向队列
deque<InternalData> maximums;
// push时生成index
int curr_index = 0;
public:
void push_back(T num) {
InternalData curr = {
num, curr_index};
curr_index++;
data.push(curr);
while (!maximums.empty() && maximums.back().num < curr.num)
maximums.pop_back();
maximums.push_back(curr);