剑指 Offer 59 - II. 队列的最大值
题干:请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的均摊时间复杂度都是O(1)。
若队列为空,pop_front 和 max_value 需要返回 -1
分析:利用两个栈定义队列,再用一个栈存放最大值。(x)
进一步分析:队列的特点是先进先出,若要判断其max或min,不能直接采用栈的方式。假设队列元素为942353637。若采用栈的方式第一个元素9低于个进,同样也会第一个出去。由于后面数均小于9,辅助栈中也不存在其他元素,也就是说,9一出去,辅助栈为空,无法判断。。。。。。那么需要利用一个辅助队列,辅助队列不仅要留最大数,还得留小于最大数的数。
按照下图进一步分析:
队列2中第一个进入的元素是9,若只保留最大数,则9出去后,辅助队列不再存在其他元素,无法求最大值,故需将7也放入队列2中,即步骤2-1。
之后再进8,由于8大于7,9出队列之后、8出队列之前,最大值均是8,7无作用,故可删除7,进8,(步骤2-2)
同样,9仅队列后,8也不发挥作用,故删除8(步骤2-3)
之后进入3,再进入4,4>3,故保留4即可。
以此类推
直到最后一个元素5进去,5大于3,故3删除,5大于4,4删除。辅助队列仅存995.
总结起来,辅助队列中存在元素的作用为:辅助队列元素能掌控的范围为队列中其位置之前的元素。第2个9的范围为1-3.5的范围为4-9.(可将辅助队列看做是将军,即队列1中的小兵一定得被辅助队列的将军所掌管)
class MaxQueue {
public:
MaxQueue() {
}
int max_value() {
if (q2.empty()) return -1;
return q2.front();
}
void push_back(int value) {
// q1 push
q1.push_back(value);
// q2 push
while (!q2.empty() && q2.back() < value)
{
q2.pop_back();
}
q2.push_back(value);
}
int pop_front() {
if (q1.empty()) return -1;
else
{
if (q1.front() == q2.front()) q2.pop_front();
int popvalue = q1.front();
q1.pop_front();
return popvalue;
}
}
private:
deque<int> q1, q2;
};
/**
\* Your MaxQueue object will be instantiated and called as such:
\* MaxQueue* obj = new MaxQueue();
\* int param_1 = obj->max_value();
\* obj->push_back(value);
\* int param_3 = obj->pop_front();
*/
}