Leetcode 232. Implement Queue using Stacks

题目描述

解法性能

我的思路

题意要求我们用栈实现队列。栈的特点是后进先出,队列的特点是先进先出——也就是说,我们需要用带有逆序特点的数据结构来实现顺序特点的数据结构,那我们只要两次逆序,不就变成正序了嘛。这提示我们用两个栈实现一个队列。

队列的主要功能是push和pop。如果我们把一个栈中元素出栈的顺序维护成队列的出队顺序,那实现起push和pop功能就比较直观了。这也比较好做,就是选一个栈(记做A)作为输出元素的栈,另一个栈(记做B)作为临时存储元素的栈。只要A中的元素出栈顺序与队列的元素出队顺序一致,那么队列的pop功能就实现了。如何让A中元素顺序与队列出队顺序保持一致呢——只要每次push一个元素的时候,我们把A中元素全都放入B中,在B的栈顶再push新加的元素,最后把B中元素放入A中就行了。

上面这个思路是可行的,可是问题在于,它的时间复杂度是O(n)的。有没有更快的做法呢?

我们发现,实际上没必要每次push/pop元素的时候,对之前push进来的元素都做一遍处理。我们可以换一个视角来理解队列:把队列的顶部当做pop操作的输出区,把队列除top位置外的其余位置视作这个输出区的缓冲区,如图1所示:

图1

两个栈实现的队列则可看成:pop操作缓冲区的缓冲区-->pop操作的缓冲区-->pop操作的输出区,如图2所示:

图2

 

也就是说,两个栈的队列实现,相比原先的队列,多了一个缓冲区的存在。理想情况下,每个元素只需进出队列(缓冲区)一次,时间复杂度是O(2n);但是多的这个缓冲区让我们的元素需要进出两次,时间复杂度是O(4n)。这种情况下,pop/push的平均时间复杂度变成了O(1),比上一种做法要更高效。它的实现思路是:每次push元素的时候,放到缓冲区的缓冲区——栈A中;每次pop元素时,先从缓冲区——栈B中pop元素,如果栈B为空,则把栈A的元素放入栈B。

附上代码(第二种思路):

class MyQueue {
private:
	stack <int> s_in, s_out;
public:
	/** Initialize your data structure here. */
	//MyQueue()
	//{
	//	stack<int> s_in, s_out;
	//}

	/** Push element x to the back of queue. */
	void push(int x) {
		s_in.push(x);
	}

	/** Removes the element from in front of queue and returns that element. */
	int pop() {
		int res;
		if (!s_out.empty())
		{
			;
		}
		else
		{
			int temp;
			while (!s_in.empty())
			{
				temp = s_in.top();
				s_in.pop();
				s_out.push(temp);
			}
		}
		res = s_out.top();
		s_out.pop();
		return res;
	}

	/** Get the front element. */
	int peek() 
	{
		int res;
		if (!s_out.empty())
		{
			;
		}
		else
		{
			int temp;
			while (!s_in.empty())
			{
				temp = s_in.top();
				s_in.pop();
				s_out.push(temp);
			}
		}
		res = s_out.top();
		return res;
	}

	/** Returns whether the queue is empty. */
	bool empty() {
		if (!s_in.empty() || !s_out.empty())
			return false;
		return true;
	}
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值