栈和队列(1)----实现
一、题一
1、设计一个有getMin功能的栈
题目:实现一个特殊的栈,在实现栈的基本功能基础上,再实现返回栈中最小元素的操作。
要求:(1)pop、push、getMin操作的时间复杂度都是O(1)。(2)设计的栈类型可以使用现成的栈结构。
2、思路:
使用两个栈,一个栈保存当前栈中的元素,记做stackData;一个栈保存最小值的栈,记做stackMin,栈顶数据为最小的数据。
两个栈使用方案:
push【压入数据】:
假设要压入数据 x ,先压入原始栈 stackData,
然后判断stackMin是否为空,如果空,直接将 x 也压入stackMin。
如果不为空,则将 x 和 stackMin 栈顶数据比较大小,
如果 x 较小或相等,则将其压入stackMin;
如果 x 较大,则不压。
pop【弹出数据】:
从原始栈 stackData先弹出元素,记为data,然后比较当前stackMin的栈顶元素和data相等还是不等,【原因是stackMin中元素肯定比data小或者相等】。如果不等,则不操作,如果相等,则将stackMin的栈顶元素弹出。
getMin【查询最小值】:
返回stackMin中的栈顶元素。
3、代码:
import queue class Stack(): def __init__(self): self.stack = queue.LifoQueue() self.stackMin = queue.LifoQueue() def pop(self): value = self.stack.get()
if self.stackMin.empty():
print("is empyty")
valueMin = self.stackMin.get() if value != self.stackMin.get(): self.stackMin.put(valueMin) def push(self,x): self.stack.put(x) if self.stackMin.empty(): self.stackMin.put(x) else: value = self.stackMin.get() if x <= value: self.stackMin.put(value) self.stackMin.put(x) else: self.stackMin.put(value) def getMin(self): value = self.stackMin.get() self.stackMin.put(value) return value a = Stack() a.push(1) a.push(3) a.push(0) a.push(9) a.pop() print(a.getMin())
二、题二
1、由两个栈实现队列:
思路一:将stack1作为存储空间,将stack2作为临时缓冲区,入队时,直接压入stack1,出队时,将stack1中的元素依次出栈压入stack2中,再将stack2的栈顶元素弹出,最后将stack2中的元素再倒回给stack1
思路二:入队时,判断stack1是否为空,如果stack1为空,则将stack2中的所有元素都倒入stack1中,再将元素直接压入stack1,否则,直接压入stack1中
出队时,判断stack2是否为空,如果stack2为空,则将stack1中的元素倒入stack2中,在将stack2的栈顶元素弹出,否则,直接弹出stack2的栈顶元素
2、思路三:
入队时,直接压入stack1中
出队时,判断stack2是否为空,如果stack2为空,则将stack1中的元素倒入stack2中,否则直接弹出stack2中的元素
思路一与思路二相比,如果是连续出栈操作或连续进栈操作,思路二比思路一好很多。思路三最好。
详细介绍思路三如下:
stackPush栈只压入数据,stackPop只做弹出栈。
实现流程:
push:往stackPush插入;
pop:首先判断stackPop是否为空,如果空则把stackPush压入stackPop,除了其栈底元素。
如果不为空,则直接将stackPop中的栈顶元素删除;
例子:
先插入 a,b,c【往栈1压】;
删除 a 【栈2中没有元素,则将栈1的元素倒入栈2中,除了栈底的元素】;
再删除b【栈2有元素,则将栈2栈顶数据删除】
再插入d【加入栈1】
再删除c 【栈2没空,则删除栈2栈顶元素】
3、代码:
import queue class builtqueue(): def __init__(self): self.stackPush = queue.LifoQueue() self.stackPop = queue.LifoQueue() def push(self,x): self.stackPush.put(x) def pop(self): if self.stackPop.empty(): while not self.stackPush.empty(): self.stackPop.put(self.stackPush.get()) return self.stackPop.get() a = builtqueue() a.push('a') a.push('b') a.push('c') print(a.pop()) print(a.pop()) a.push('d') print(a.pop())
三、题三
1、两个队列实现一个栈:
2、思路:
将queue1用作进栈出栈,queue2作为一个中转站
入栈时,直接压入queue1中
出栈时,先将queue1中的元素除最后一个元素外依次出队列,并压入队列queue2中,将留在queue1中的最后一个元素出队列即为出栈元素,最后还要把queue2中的元素再次压入queue1中
四、题四:栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
思路:
建立一个辅助栈stack,
每次判断辅助栈stack顶部元素和popV的第一个元素是否一样,【一样则popV.pop(0)且stack.pop()】
然后判断pushV[i] 和popV的第一个元素是否一样,【一样则popV.pop(0)且 i += 1】
若不一样则stack.append(pushV[i])
总体:
建立一个辅助栈s,把序列1,2,3,4,5依次压入辅助栈s,并按照第二个序列4,5,3,2,1的顺序从辅助栈s中弹出数字。
先将序列1,2,3,4,5依次压入栈s,每次压栈时都判断栈s的当前栈顶元素跟序列4,5,3,2,1的第一个元素是否相等。当压入4之后,发现栈顶元素跟序列4,5,3,2,1的第一个元素相等。弹出栈s的栈顶元素4,然后将序列4,5,3,2,1中第一个元素去掉,序列4,5,3,2,1变成序列5,3,2,1。在执行上述过程。
代码:
def IsPopOrder(self, pushV, popV): # write code here if not pushV: return True stack = [] i = 0 while i < len(pushV): while stack and stack[-1] == popV[0]: popV.pop(0) stack.pop() if pushV[i] == popV[0]: popV.pop(0) i += 1 else: stack.append(pushV[i]) i += 1 while popV: if popV[0] != stack[-1]: return False else: popV.pop(0) stack.pop() return True