编程之美上的题目,具体忘记了,有一个队列,定义了push,pop,MaxElement三个函数,其中MaxElement要返回队列中最大的元素,第一次看这个题目就是遍历,每次MaxElement的时候遍历一遍队列,具体代码不写了,三个操作的开销为:
2 pop:O( 1 )
3 MaxElement:O(Length(que))
于是换成另外一种方法,设置一个MaxVal,每次push与进入队列的元素进行比较,这样代码如下:(为了节省篇幅,利用了STL)
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,那么就必须进行更新,三个操作的开销分别为
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掉,具体代码如下:
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 que,buf_que;
};
参考资料:
<<编程之美>>,最后这题用栈的没看懂,过几天有空在看
这下面的资料看看对解这道题有帮助:
http://zhedahht.blog.163.com/blog/static/2541117420073293950662/
http://zhedahht.blog.163.com/blog/static/25411174200712895228171/