昨天在九章算法上看到的一个问题:
在栈上实现Min方法,由于栈后入先出的特点,实现Min方法很容易想到同时维护一个minValue的栈,栈顶元素保持是normal stack中所有元素的min value,现在问如何在队列上实现一个Min方法,要求,队列除了支持基本的push(x),pop()方法以外,还需支持min方法,返回当前队列中的最小元素,每个方法的均摊复杂度为O(1)。
思考过程:
容易实现在push新元素后更新当前min值,但如何在pop队首元素后保证紧接着的min调用是难点,想着想着,想到同时维护一个保存minValue的队列,维持队列内的仅存放所有的minValue:
template <typename T>
class MinQueue
{
private:
queue<T> normalQueue;
queue<T> minValueQueue;
public:
bool empty()const{
return normalQueue.empty();
}
void push(const T& item){
normalQueue.push(item);
if(minValueQueue.empty()){
minValueQueue.push(item);
}
else if(minValueQueue.front() > item){
while(!minValueQueue.empty()) minValueQueue.pop();
minValueQueue.push(item);
}
else if(minValueQueue.front() == item){
minValueQueue.push(item);
}
}
T pop(){
T tmp = normalQueue.front();
normalQueue.pop();
if(tmp == minValueQueue.front()){
minValueQueue.pop();
}
return tmp;
}
T min(){
return minValueQueue.front();
}
};
很容易看出min方法是O(1)的,pop方法也是O(1)的,push方法中包含一个while循环,一次操作中有可能不是O(1)的,但由于所有元素最多一进一出minValueQueue,所以其均摊开销是O(1)的。
PS:总感觉这个思想有点像单调队列,只不过这里仅存储了最小值……