纯粹是为了提高专注度,逼迫自己放下手机,就来写一写这个东西。
用两个栈来实现一个队列,leetcode剑指offer第9题,链接如下
写在前面:栈:先进后出
队列:先进先出
两者都是限制存取点的线性结构。
解决问题:
用栈来实现队列。那么首先问题是,python中怎么实现栈的呢?最方便的办法就是list了。入栈:list.append() 将数据加入列表尾部
出栈:list.pop() 弹出列表最后一个元素
list 的 append 功能实现栈的 push 操作
list 的 pop 功能实现栈的 pop 操作
所以栈我们有了,题目中说让使用两个栈,我们使用一个具体例子来说明一下:现在是 队列的 push 操作,依次push了 1 2 3 4 5,那栈中的元素如下图中的(1)所示。
那如果现在要pop呢?根据队列的性质,我们应该首先pop的是1,但是我们用的是栈,如果
那个栈直接pop的话,应该pop出的是6,所以我们这个时候可以借助栈
.
把
栈的元素压入
栈中,那么最先进去的 1 就位于栈
的顶端了,栈
pop的结果作为队列pop的结果,那么就是正确的了。
在这个过程中栈
被用作存储栈,栈
被用作缓存栈(即将被弹出)
python代码实现:
class CQueue:
def __init__(self):
self.A,self.B = [],[]
def appendTail(self, value: int) -> None:
self.A.append(value)
def deleteHead(self) -> int:
# 缓冲区有内容,直接pop最顶层
if self.B : return self.B.pop()
# 缓冲区和存储区都空,是个空队列,返回-1
if not self.A: return -1
# 缓冲区为空,将存储区的数据压入缓冲区
while self.A:
self.B.append(self.A.pop())
return self.B.pop()
代码中可能有些迷糊的地方,总是晕晕的,第二次写不一定能写对:队列的push操作没什么可说的了,直接存储区append进来就行
至于他的pop操作:首先,缓冲区中有数据,则直接缓冲区pop就行
缓冲区没数据,存储区也没数据,那就直接空了啊,返回-1
缓冲区没数据,存储区有数据,那就说明你上一把缓冲的最早的一些数据已经pop完了,你再把存储区的数据再全部放到缓冲区去,以备待用。再缓冲区pop,完事。
有一点很重要,一定要缓冲区为空之后,存储区的数据才能再次转移。才能保证队列弹出数据的正确性。
变形金刚之问题进阶:
其实这道题也还行,我今天吧,做牛客网上京东那个算法岗的试题,有个问题是这样的:
用俩个栈模拟实现一个队列,如果栈的容量分别是O和P(O>P),那么模拟实现的队列最大容量是多少?
这个,害,菜鸟的我当然一上来就蒙了啊。首先的首先,咱们得理解啥叫容量吧?应该就是你一个劲的一个劲地push进去,不准中途pop,直到你再push进去的话,再pop出来的就不是列表正常的pop了,就破坏列表结构了。所以咱们理解起来就是:不影响队列性质的前提下,能一直pop进去的元素数目。
然后才是首先,O和P,存储区和缓存区的选择。如果P是存储区,P装满后,往O移动,移动完了之后,O没满,P为空,再不pop的前提下,P还能装P个。这个时候O虽然不是空的,但是不能往O转移,因为那样会乱了队列的弹出顺序。所以这个容量就是2P。
如果O是存储区的话,O不能直接装满,因为装满的话转移到P中,P的栈顶元素不是第一个进去O的元素,所以一开始只能装P个,O装完P个,往P里转移,O还可以装P个肯定没问题,这缓冲区P本来就有P个,pop出去,顺序没问题,O里新装的P个,也转到缓冲区再pop出去,也没问题。那如果O这次多装一个呢,装P+1个的话,P个被转移到P里(第P+2到2P+1个元素),O里还剩一个(第P+1个),那这一个(第P+1个元素)会转移到P里,那么这个时候如果我们pop O中的元素,就成功的pop出了第P+1个元素,然后再pop P里的P个元素,这个顺序是没错的。所以说第二次装P+1个没问题耶。那大胆一点,再多装一个?假设第二次装了P+2个,那前P个被移到缓冲区,O里还剩两个(第P+1,P+2个),那这个时候无论pop哪个栈里的元素,都没办法把第P+1个元素pop出来,所以不行了。所以,只能多一个,也就是容量是2P+1。
容量是2P+1的前提是,存储区在P+1的时候pop了,之前咱们实现的栈,pop是缓冲区的事哦。
所以记住了:两个栈实现队列的最大容量为 2P+1 ,其中P是较小的栈的容量,且大栈当存储区,小栈当缓冲区。大栈需要pop出第P+1个元素。
在整个出队的过程中为了实现最大容量,不仅仅只有s2在输出,在必要的时候(即第p+1元素),s1也要直接输出,但是必须明白的是,s1最多只能直接输出一个元素(即s1中最多存储P+1个元素),多出两个往上都会违反队列的先进先出原则。
参考一下哦:用两个栈模拟一个队列,栈的容量分别是O和P(O>P),讨论队列可以实现的最大容量_平凡之路-CSDN博客_用俩个栈模拟实现一个队列,如果栈的容量分别是o和p(o>p),那么模拟实现的队列最大blog.csdn.net