编程之美上的题目,具体忘记了,有一个队列,定义了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/