01-用两个栈实现队列
题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
复习:
栈的特性:先进后出
队列的特性:先进先出
思路:
解析:使用两个栈来实现一个队列,其实就是组合两个栈,来实现队列,栈是先进后出,队列是先进先出,可使用以下操作使用栈来实现队列:
一、入队列:
把需要存放的元素插入到栈1中
二、出队列:
**ps:此时栈顶元素就是需要出队列的元素
入栈时数据存入栈stackIn, 出栈时数据从stackOut弹出。执行入栈操作时,将数据源源不断的压入栈stackIn;执行出栈操作时,将stackIn的数据一次性全部弹出,存入到stackOut中。当stackOut栈非空时,不断弹出stackOut栈中的数据顺序即为队列的Pop顺序;当stackOut中的数据为空后,再将新入栈stackIn的数据一次性存入stackOut中即可。相比于上一种方式,这种方式极大降低了数据在栈stackIn和栈stackOut中来回无意义的腾挪操作,占据更低的存储空间,消耗更低的运算时间。
class Solution:
def __init__(self):
self.stackIn = []
self.stackOut = []
def push(self, node):
self.stackIn.append(node)
def pop(self):
if not self.stackOut:
while self.stackIn:
self.stackOut.append(self.stackIn.pop(-1))
return self.stackOut.pop(-1) #(-1)代表从顶部pop
# 实例化
if __name__=='__main__':
node=[1,2,4,7,3,5,6,8]
demo = Solution()
print(demo.push(node),demo.pop())
02-包含min函数的栈,栈的压入弹出
题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))
思路:链接: 看到这个问题, 我们最开始可能会想, 添加一个成员变量用于保存最小元素, 每次压栈时如果压栈元素比当前最小元素更小,
就更新最小元素.
但是这样会有一个问题, 如果最小元素被弹出了呢, 如何获得下一个最小元素呢? 分析到这里可以发现, 仅仅添加一个成员变量存放最小元素是不够的, 我们需要在最小元素弹出后还能得到次小元素, 次小的弹出后, 还要能得到次次小的.
因此, 用另一个栈来保存这些元素是再合适不过的了. 我们叫它最小元素栈.
每次压栈操作时, 如果压栈元素比当前最小元素更小, 就把这个元素压入最小元素栈, 原本的最小元素就成了次小元素. 同理, 弹栈时, 如果弹出的元素和最小元素栈的栈顶元素相等, 就把最小元素的栈顶弹出.
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.arr=[]
def push(self, node):
# write code here
self.arr.append(node)
def pop(self):
# write code here
return self.arr.pop()
def top(self):
return self.arr[-1]
def min(self):
# write code here
return min(self.arr)
21,题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
思路
栈的压入顺序是指1,2,3,4,5是依次push到栈的,但并不是说只有push的过程,也可能有pop的操作,比如push
1,2,3,4之后,把4pop出去,然后再push5,也是一样的压入顺序;弹出序列是指每次pop出去的元素都是当时栈顶的元素,比如一开始pop1,2,3,4,然后pop4,再push5,再pop5,然后依次pop3,2,1,那么弹出序列就是4,5,3,2,1;那么就可以构造一个辅助栈来判断弹出序列是不是和压栈序列对应。首先遍历压栈序列的元素push到辅助栈,判断是不是弹出序列的首元素,如果是,则弹出序列pop首元素(指针后移),如果不是,则继续push,再接着判断;直到遍历完了压栈序列,如果辅助栈或者弹出序列为空,则返回True,否则返回False
**
总的来说,判断一个序列是不是栈的弹出序列,主要把握一个规律:
如果下一个弹出的数字刚好是栈顶数字,那么直接弹出;
如果下一个弹出的数字不在栈顶,我们就要把压栈序列中还没有入栈的数字压入辅助栈,
直到把下一个需要弹出的数字压入栈顶为止;
如果所有的数字都压入了栈中仍然没有找到下一个弹出的数字,那么该序列就不可能是一个合法的弹出序列
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190222142404477.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzI0NDI5MzMz,size_16,color_FFFFFF,t_70)
思路:利用一个辅助栈来存放最小值
栈 3,4,2,5,1
辅助栈 3,3,2,2,1
每入栈一次,就与辅助栈顶比较大小,如果小就入栈,如果大就入栈当前的辅助栈顶
当出栈时,辅助栈也要出栈
这种做法可以保证辅助栈顶一定都当前栈的最小值
实例化
链接:https://www.nowcoder.com/questionTerminal/d77d11405cc7470d82554cb392585106
来源:牛客网
【思路】借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。
举例:
入栈1,2,3,4,5
出栈4,5,3,2,1
首先1入辅助栈,此时栈顶1≠4,继续入栈2
此时栈顶2≠4,继续入栈3
此时栈顶3≠4,继续入栈4
此时栈顶4=4,出栈4,弹出序列向后一位,此时为5,,辅助栈里面是1,2,3
此时栈顶3≠5,继续入栈5
此时栈顶5=5,出栈5,弹出序列向后一位,此时为3,,辅助栈里面是1,2,3
….
依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。
**
#如果stack的最后一个元素与popV中第一个元素相等,将两个元素都弹出
class Solution:
def IsPopOrder(self, pushV, popV):
# write code here
if not pushV or len(pushV)!=len(popV): # 如果数据长度不等返回0
return 0
stack = [] # 定义辅助栈
for v in pushV:
stack.append(v) #把压栈顺序的添加到辅助栈中
while len(stack) and stack[-1]==popV[0]: #辅助栈不为空当辅助栈不为空且栈顶元素等于弹出元素时
stack.pop()
popV.pop(0)
if len(stack):
return 0
return 1
stack【-1】栈里 栈顶的值是存在val[- 1]里,popV 是序列,它与数组元素的对应关系,应该是 val[0]是第1个元素.
# -*- coding:utf-8 -*-
class Solution:
def IsPopOrder(self, pushV, popV):
# stack中存入pushV中取出的数据
stack=[]
while popV:
# 如果第一个元素相等,直接都弹出,根本不用压入stack
if pushV and popV[0]==pushV[0]:
popV.pop(0)
pushV.pop(0)
#如果stack的最后一个元素与popV中第一个元素相等,将两个元素都弹出
elif stack and stack[-1]==popV[0]:
stack.pop()
popV.pop(0)
# 如果pushV中有数据,压入stack
elif pushV:
stack.append(pushV.pop(0))
# 上面情况都不满足,直接返回false。
else:
return False
return True
思路2“这个可考虑”
解题思路:当前出栈为a,则下一个出栈的数字在入栈序列中,可以是排在它后面的任意一项,也可以是他前面的项,但跟她的索引值之差不能大于1.需要注意的是它也可能不在原来的序列中,所以要先判断它是否存在,在用.index函数找索引
# -*- coding:utf-8 -*-
class Solution:
def IsPopOrder(self, pushV, popV):
# write code here
list_len = len(pushV)
for i in range(len(popV)):
pop_num = popV.pop(0)
if pushV.count(pop_num):
index = pushV.index(pop_num)
if popV:
if pushV[index:len(pushV)].count(popV[0]) or (pushV[0:index].count(popV[0]) and abs(pushV[0:index].index(popV[0])- index)==1):
pushV.pop(index)
else:
return False
else:
return True
else:
return False
原文:https://blog.csdn.net/Jillian_sea/article/details/80339471