版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vivian_ll/article/details/88186936
栈的特点就是后进先出,需要O(N)的时间才能找到栈中的最值。
队列和栈刚好相反,是先进先出,表面上和栈是一对矛盾体,但实际上,都可以利用对方来实现自己。
1.用两个栈实现一个队列
思路:
入队:元素进栈A
出队:先判断栈B是否为空,为空则将栈A中的元素 pop 出来并 push 进栈B,再栈B出栈,如不为空则栈B直接出栈
改进:
入队:元素进栈A
出队:先判断栈B是否为空,为空则将栈A中的n-1个元素 pop 出来并 push 进栈B,最先压入栈A的元素不pop再push到栈B,直接从栈A pop出栈,如不为空则栈B直接出栈
注意怎样把Queue的操作和Stack的操作联系起来
class MyQueue:
def __init__(self):
"""
Initialize your data structure here.
"""
# 初始化
self.stack1 = Stack()
self.stack2 = Stack()
def push(self, x):
"""
Push element x to the back of queue.
:type x: int
:rtype: void
"""
self.stack1.items.append(x)
def pop(self):
"""
Removes the element from in front of queue and returns that element.
:rtype: int
"""
if self.stack2.isEmpty()!=True: #判断栈2是否为空
return self.stack2.items.pop()
else:
if self.stack1.isEmpty()!=True:
while self.stack1.size()!=1:
self.stack2.items.append(self.stack1.items.pop())
return self.stack1.items.pop()
else:
if self.stack2.isEmpty() != True:
return self.stack2.items.pop()
def peek(self):
"""
Get the front element.
:rtype: int
"""
if self.stack2.isEmpty() != True:
if len(self.stack2.items) >= 1:
return self.stack2.items[len(self.stack2.items) - 1]
else:
if self.stack1.isEmpty() != True:
return self.stack1.items[0]
else:
return False
def empty(self):
"""
Returns whether the queue is empty.
:rtype: bool
"""
return self.stack1.items == [] and self.stack2.items == []
def size(self):
return len(self.stack1.items)+len(self.stack2.items)
2.定义栈的数据结构,在该类型中实现一个能够得到栈的最小元素的min函数,在该栈中,要求调用min,push和pop的时间复杂度都是O(1)
我们首先的第一想法就是在每次将元素压入栈的时候,保留当前的最小值,但仔细想想,如果最小值已经被弹出栈了,又该如何得到剩下元素中的最小值呢?
我们可以使用一个辅助栈,每次压入元素的时候,将最小值压入,每次弹出元素的时候,也将最小值弹出,确保这两个栈的动作是同步的。
class MinStack:
# def __init__(self):
# """
# initialize your data structure here.
# """
# self.stack = []
#
# def push(self, x: int) -> None:
# self.stack.append(x)
#
#
# def pop(self) -> None:
# return self.stack.pop()
#
# def top(self) -> int:
# return self.stack[-1]
#
# def getMin(self) -> int:
# return sorted(self.stack)[0]
# # 或 return min(self.l)
def __init__(self):
self.stack = []
self.minimum = [] # 按顺序存放当前的最小值
def push(self, x):
self.stack.append(x)
try:
oldMin = self.minimum[-1]
if x < oldMin:
self.minimum.append(x)
else:
self.minimum.append(oldMin)
except:
self.minimum.append(x)
def pop(self):
self.minimum.pop()
return (self.stack.pop())
def top(self):
return (self.stack[-1])
def getMin(self):
return (self.minimum[-1])
3.输入两个整数序列,第一个序列表示压栈顺序,判断第二个序列是否是弹出顺序
思路:
如果下一个弹出的数字刚好是栈顶数字,那么直接弹出。
如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。
如果所有的数字都压入栈了仍然没有找到下一个弹出的数字,那么该序列不可能是一个弹出序列。
def validateStackSequences(self, pushed, popped) -> bool:
# 贪婪算法 均为O(N)
j = 0
newstack = [] # 压入栈
for x in pushed:
newstack.append(x)
while newstack and newstack[-1] == popped[j]: # popped[j]为弹出序列当前最顶上元素
newstack.pop()
j += 1 # 计数 当前有多少数对应上
return j == len(popped) # 相当于 return not newstack