编程之美之队列中取最大值操作

问题:

假设有这样一个拥有3个操作的队列:

1. EnQueue(v): 将v加入队列中

2. DeQueue(): 使队列中的队首元素删除并返回此元素

3. MaxElement: 返回队列中的最大元素

设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低。

#include<iostream>
#include<limits.h>
using namespace std;

class Stack
{
	public:
		Stack()
		{
			stackTop = -1;
			maxStackItemIndex = -1;
		}
		void Push(int x)
		{
			if(stackTop >= MAXN - 1)return;
			stackItem[++stackTop] = x;
			if(x > Max())
			{
				link2NextMaxIten[stackTop] = maxStackItemIndex;//保存下一个最大值的位置
				maxStackItemIndex = stackTop;//保存当前最大值
			}
			else link2NextMaxIten[stackTop] = -1;
		}
		int Pop()
		{
			if(stackTop >= 0)
			{
				int value = stackItem[stackTop];
				if(stackTop == maxStackItemIndex)maxStackItemIndex = link2NextMaxIten[stackTop];//改变当前最大值
				--stackTop;
				return value;
			}
		}
		bool Empty()
		{
			return stackTop == -1;
		}
		int Max()
		{
			if(maxStackItemIndex >= 0)return stackItem[maxStackItemIndex];
			else return INT_MIN;
		}
	private:
		const static int MAXN = 100;
		int stackTop;
		int maxStackItemIndex;
		int stackItem[MAXN];
		int link2NextMaxIten[MAXN];
};

class Queue
{
	public:
		void EnQueue(int v)
		{
			stk2.Push(v);
		}
		int DeQueue()
		{
			if(stk1.Empty())
			{
				while(!stk2.Empty())
				{
					stk1.Push(stk2.Pop());
				}
			}
			return stk1.Pop();
		}
		int MaxElement()
		{
			return max(stk1.Max(),stk2.Max());
		}
	private:
		Stack stk1;
		Stack stk2;
};

对比:剑指offer之取栈中最小值操作

题目:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop的时间复杂度都是O(1)。

分析:我们需要一个辅助栈。每次push一个新元素的时候,同时将最小元素(或最小元素的位置。考虑到栈元素的类型可能是复杂的数据结构,用最小元素的位置将能减少空间消耗)push到辅助栈中;每次pop一个元素出栈的时候,同时pop辅助栈。具体代码如下

template<class T>
class Stack
{
	public:
		void push(const T& value)
		{
			value_stk.push(value);
			if(!min_stk.empty())
			{
				if(value < min_stk.top())min_stk.push(value);
				else min_stk.push(min_stk.top());
			}
			else min_stk.push(value);
		}
		void pop()
		{
			value_stk.pop();
			min_stk.pop();
		}
		T min()const
		{
			assert(!value_stk.empty() && !min_stk.empty());
			return min_stk.top();
		}
	private:
		stack<T> value_stk;//存放数据的栈
		stack<T> min_stk;//存放最小值的栈
};

两个队列实现一个堆栈:

思路:整个过程中保持一个队列有数据,一个队列为空。push的时候往有数据的一个对列中加入,pop的时候,把有数据的队列除最后一个元素以外的push到另一个空队列中,最后一个元素删除,用inputQueue和outputQueue指针分别指向这两个队列

template <class T>
class Stack
{
	public:
		bool empty()
		{
			return q1.size() == 0 && q2.size() == 0;
		}
		void push(const T& value)
		{
			queue<T>* inputQueue = &q1;
			if(q1.size() == 0)inputQueue = &q2;
			inputQueue -> push(value);
		}
		T top()
		{
			queue<T>* inputQueue,*outputQueue;
			if(q1.size() == 0)
			{
				inputQueue = &q2;
				outputQueue = &q1;
			}
			else
			{
				inputQueue = &q1;
				outputQueue = &q2;
			}
			assert(inputQueue->size() > 0);
			while(inputQueue->size() > 1)
			{
				outputQueue->push(inputQueue->front());
				inputQueue->pop();
			}
			T value = inputQueue->front();
			outputQueue->push(inputQueue->front());
			inputQueue->pop();
			return value;
		}
		void pop()
		{
			queue<T>* inputQueue,*outputQueue;//inputQueue指向有数据的队列,outputQueue指向空队列
			if(q1.size() == 0)
			{
				inputQueue = &q2;
				outputQueue = &q1;
			}
			else
			{
				inputQueue = &q1;
				outputQueue = &q2;
			}
			assert(inputQueue->size() > 0);
			while(inputQueue->size() > 1)
			{
				outputQueue->push(inputQueue->front());
				inputQueue->pop();
			}
			inputQueue->pop();
		}
	private:
		queue<T> q1;//两个工作队列,同一时间只有一个有数据
		queue<T> q2;
};

编程之美之队列中取最大值操作

时间: 2024-12-28 06:09:52

编程之美之队列中取最大值操作的相关文章

队列中取最大值操作

假设有这样一个拥有3个操作的队列: 1.EnQueue(v):将v加入队列 2.DeQueue:使队列中的队首元素删除并返回元素 3.MaxElement:返回队列中的最大元素 请设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能低 研究这个问题之前,先研究两个子问题: 1.设计一个包含min操作的栈 2.用栈实现队列 一.设计一个包含min操作的栈 考虑给栈增加一个成员变量MinValue,有元素入栈的时候,将入栈元素与MinValue相比,如果小于MinValue,用入栈元

编程之美---队列中取最大值操作问题

如何快速获取队列中的最大值? 最简单的办法,用一个for循环遍历,复杂度为o(n). 解法二:用大顶堆来实现,复杂度为哦o(1),但是入队和出队复杂度变为o(logN),堆中的每一个元素还得有个指针指向它的后继元素. 解法三:可以使用两个栈来模拟队列,从右边的栈进入元素相当于入队,出队时,只有当左边的栈为空时,才把右边栈的元素全部出栈到左边的栈. 1 class stack 2 { 3 public: 4 stack() 5 { 6 stackTop = -1; 7 maxItemIndex =

&lt;&lt;编程之美&gt;&gt; -- 队列中取最大值操作的问题

不得不说编程之美是一本好书,虽然很多题目在做acm中的过程中遇到过,不过还是有很多值得思考的地方 这是今天在编程之美上看到的一个问题,对于栈转化成队列的一个思考 平时都太过依赖c++内函数库中的栈和队列,但是对于他们的扩展我们还是应该自己进行手写栈和队列来实现更简单的算法 题目大意: 假设有这样一个拥有3个操作的队列: 1. EnQueue(v) : 将 v 加入队列 2. DeQueue: 使队列中队首元素删除并返回此元素 3.MaxElement: 返回队列中的最大元素 设计一种数据结构和算

编程之美——队列中取最大值操作

为实现O(1)的时间复杂度完成取队列中最大元素,使用maxStackItemIndex记录队列(使用两个栈实现)中最大元素下标,使用数组link2NextMaxItem[]记录数组中次大值的下标,这也就是使用两个栈(先进后出)模拟队列二不是直接使用队列(先进先出)的原因:先进后出可以保证当执行pop操作(pop出最大值)时可以更新maxStackItemIndex=link2NextMaxItem[stackTop]:而队列则不具有这种回溯特性: 代码: 1 #include<iostream>

队列中取最大值操作问题

问题: 假设有这样一个拥有3个操作的队列: 1. EnQueue(v): 将v加入队列中 2. DeQueue(): 使队列中的队首元素删除并返回此元素 3. MaxElement: 返回队列中的最大元素 设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低. 思路: (1)用两个栈设计一个新的数据类型(数据类型定义为MyStack),其中一个栈用来存放数据,另一个栈用来存放最大值, 当插入数据时,第一个栈接受数据进行入栈操作,第二栈首先判断一下栈顶元素和插入元素的大小,如果

3.7 队列中取最大值操作问题

问题: 假设有这样一个拥有3个操作的队列: 1. EnQueue(v): 将v加入队列中 2. DeQueue(): 使队列中的队首元素删除并返回此元素 3. MaxElement: 返回队列中的最大元素 设计一种数据结构和算法,让MaxElement操作的时间复杂度尽可能地低. 方法:用两个栈来模拟队列 在代码中,maxStackItemIndex代表栈中最大的数的下标 link2NextMaxItem[index]表示当前index这个下标代表的数字(当前是最大的)如果没有的话,那么最大的那

程之美第3章结构之法-字符串及链表的探索3.7 队列中取最大值操作问题

#include<iostream> #include<vector> using namespace std; class stack { private: vector<int> vec;//用来保存当前进栈的值 vector<int> max_vec; public: void push(int a) { vec.push_back(a); if(max_vec.size()==0||a>vec[max_vec[max_vec.size()-1]

编程之美----寻找数组中的最大值和最小值

对于一个由N个整数组成的数组,需要比较多少次才能把最大和最小的数找出来呢? 解法:最简单的是扫描一遍数组,需要比较2*N次才能求解. 解法二:首先在概念上把连个相邻的数分在同一组,只是想象而已,无须任何操作.然后比较同一组的奇数位数字和偶数位数字,将较大的数放在偶数位上,较小的数放在奇数位上.N/2次比较久可以调好.然后求出偶数位上的Max,和奇数位上的Min,各须比较N/2次.总共须比较1.5*N次.  若不破坏原数组,只需用两个变量Max和Min来存储当前的最大值和最小值,当比较完奇数位和偶

编程之美:队列中的最大最小值

#include "iostream" #include "memory.h" #include "stdio.h" #include "limits.h" typedef int Type; const int MAXN=15; const int MIN=INT_MIN; class stack { public: stack() { stacktop=-1; maxItemIndex=-1; } void push(Ty