基本概念:
栈
什么是栈
栈是一种特殊的线性表,其差别是,栈只允许在固定一端进行插入和删除数据元素操作。允许进行插入和删除数据元素的一端称为栈顶,另一端称为栈底。
根据堆栈定义,每次进栈和出栈都在同一端。每次进栈的数据元素都放在原当前栈顶元素之前,成为新的栈顶元素;每次退栈的数据元素都是当前栈顶元素。因此,每次最后进入的数据元素,都会最先退出,被称之为后进先出表。
栈的本质
栈的功能实际上是从某种数据元素序列到另一种数据元素序列的转换。
队列
队列也是一种特殊的线性表,其差别是:队列只允许在其一端进行插入操作,在其另一端进行删除操作,允许插入操作的一端称为队尾,允许进行删除操作的一端称为队头。
根据队列的定义,每次入列的数据元素都放在原来的队尾数据元素之后成为新的队尾元素,每次出列的数据元素都是原来的队头元素。这样,最先入列的数据元素总是先出队列,所以队列是一种先进先出的线性表简称先进先出表。
题目一:用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
来源:力扣(LeetCode)
想要在队列尾部插入整数可以在一个栈中实现,但是要在头部删除整数,就需要另外一个栈来辅助操作。
解题思路:
要想将新加入的元素出现栈底,将stack1视为队列
在队列尾部插入整数: 将stack1中的队列转移到stack2,在stack1中让入新元素入栈,最后让stack2中的元素回到stack1中,插入成功。
在队列头部删除整数:直接在stack1中删除头部元素即可,如果队列为空则返回-1
解题思路:
算法实现:
class CQueue:
def __init__(self):
self.stack1 = []
self.stack2 = []
def appendTail(self, value: int) -> None:
while self.stack1:
self.stack2.append(self.stack1.pop())
# add value
self.stack1.append(value)
# 1 <- 2
while self.stack2:
self.stack1.append(self.stack2.pop())
return self.stack1
def deleteHead(self) -> int:
if not self.stack1: return -1
return self.stack1.pop()
题目二:包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
来源:力扣(LeetCode)
本题难点在于让时间复杂度都为1
解题思路:
我们准备了两个栈,数据栈stack1用于存储所有元素,数据栈stack2用于存储栈stack2所有非严格降序的元素,则栈stack1中的最小元素永远都是stack2的栈顶元素,所以min()函数直接输入栈b的栈顶元素。
函数设计过程:
push()函数:当stack1中加入新元素,如果stack2为空或新入元素小于stack2的栈顶元素,则在stack2加入该元素。
pop()函数:确保stack1,stack2中元素的一致性。
top()函数:直接返回stack1的栈顶元素
min()函数:返回stack2的栈顶元素,即stack1中的最小元素
算法实现:
class MinStack:
def __init__(self):
self.stack1=[]
self.stack2=[]
def push(self, x: int) -> None:
self.stack1.append(x)
if not self.stack2 or self.stack2[-1] >= x:
self.stack2.append(x)
def pop(self) -> None:
if self.stack1.pop() == self.stack2[-1]:
self.stack2.pop()
def top(self) -> int:
return self.stack1[-1]
def min(self) -> int:
return self.stack2[-1]