如何在一个队列中查找最大值

编程之美上的题目,具体忘记了,有一个队列,定义了push,pop,MaxElement三个函数,其中MaxElement要返回队列中最大的元素,第一次看这个题目就是遍历,每次MaxElement的时候遍历一遍队列,具体代码不写了,三个操作的开销为:

1 push:O(1)
2 pop:O(1)
3 MaxElement:O(Length(que))

于是换成另外一种方法,设置一个MaxVal,每次push与进入队列的元素进行比较,这样代码如下:(为了节省篇幅,利用了STL)

1 int main(void)
2 {
3 queue<int> que;
4 int MaxVal=-1;
5 int push_data[5]={
6 9,8,10,2,1
7 };
8
9 for(int i=0;i<5;i++)
10 {
11 if(MaxVal<push_data[i])
12 MaxVal=push_data[i];
13 que.push(push_data[i]);
14 }
15 cout<<MaxVal<<endl;
16 }

这样的话只要调用MaxElement的时候只要返回MaxVal就可以了

这样看起来好像没有问题,有一个没想到的地方,就是pop的时候,如果pop是MaxVal的值,那么MaxVal也要进行更新,比如把push_data的元素改成:9,8,5,2,1,那么当第一次调用pop的时候,由于MaxVal为队列的top,那么就必须进行更新,三个操作的开销分别为

1 push:O(1) 
2 pop:O(1) || O(Length(que))  
3 MaxElement:O(1)

后来想起好像在一个网站看过类似这种题目,找了下,在一个栈中查找最小值,有点像吧传送门如下:

http://zhedahht.blog.163.com/blog/static/25411174200712895228171/ 

这个是通过辅助栈来做的,看起来这题也可以用辅助队列,不过要小心了,如果你只是照搬这个的思想,会有个问题,举个例子,比如我按照顺序像队列push了1,2,4,3,那么辅助队列则是:1,2,4,4,这个时候你弹出第一个最大元素会是多少,1,错误了吧

修改下,每次push的时候如果发现当前辅助数组的最大值小于要push的值,则清空原来的辅助数组,代码如下:

	void push(const int &x)
	{
		que.push_front(x);
		while(!buf_que.empty() && x > buf_que.back())
			buf_que.pop_back();
			
		buf_que.push_back(x);
	}

这样你push了1,2,4,3后,辅助队列的值为4,3,那么pop呢??只要pop的时候发现pop的数==辅助队列的头元素,则把辅助队列头个元素pop掉,这样只有pop掉4后才会把辅助数组的4给pop掉,具体代码如下:

1 void pop()
2 {
3 if(que.front()==buf_que.front())
4 {
5 buf_que.pop_back();
6 }
7 que.pop_front();
8 }

完整的类如下:

 

class Queue
{
public:
	void pop()
	{
		if(que.front()==buf_que.front())
		{
			buf_que.pop_back();
		}
		que.pop_front();
	}
	
	void push(const int &x)
	{
		que.push_front(x);
		while(!buf_que.empty() && x > buf_que.back())
			buf_que.pop_back();
			
		buf_que.push_back(x);
	}
	
	int MaxElement()
	{
		return buf_que.front();
	}
private:
	deque<int> que,buf_que;
	
};

参考资料:

<<编程之美>>,最后这题用栈的没看懂,过几天有空在看

这下面的资料看看对解这道题有帮助:

http://zhedahht.blog.163.com/blog/static/2541117420073293950662/ 

http://zhedahht.blog.163.com/blog/static/25411174200712895228171/ 

原文地址:https://www.cnblogs.com/linyilong3/p/2060695.html