1有效的括号(10分)题目内容:给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]'的字符串,判断字符串是否有效。
有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。注意空字符串可被认为是有效字符串。
输入格式:
一行字符串
输出格式:
True或False,表示该输入是否为合法括号串
输入样例1:
([])
输出样例1:
True
输入样例2:
{{)]}
输出样例2:
False
解题思路:
1.从左往右遍历字符串
2.最新遇到(扫描到右括号之前最晚遇到)的左括号,应该与最先遇到的右括号匹配;最先遇到的左括号,应该与最晚遇到的右括号匹配。这种次序反转的识别与栈的LIFO特性(后进先出 Last in First out )符合。
那么,创建一个栈来暂存左括号“(”,在没遇到右括号之前,左括号全部压入栈顶,遇到右括号时,从栈里面pop出最新遇到的左括号,就可以很好的匹配了。
(1)如果在遇到右括号时,栈空了,则说明括号不能成功匹配,右括号多了
(2)如果扫描完了,栈还没空,则说明括号不能成功匹配,左括号多了
(3)如果在扫描完之后,栈空了且左右括号能完全匹配,则说明匹配成功。
3.解决“左括号必须用相同类型的右括号闭合”的问题:
(1)可以在遇到右括号时,判断从站里面pop出来的左括号是否与右括属于同类型,同类型则能匹配,不同类型则匹配失败。
(2)可以用列表的index方法来实现,在两个列表里,将括号的类型与位置做统一规定,index后的返回值相同的话,则说明左右括号属于同类型。
ls1=["(","[","{"]
ls2=[")","]","}"]
return ls1.index(Stack.pop())==ls2.index(token)
#栈顶pop出的左括号是否匹配当前遇到的右括号(token)
程序代码:
#有效的括号
class Stack(): #定义栈的类,一会直接调用方法
def __init__(self):
self.items=[]
def isEmpty(self):
return self.items == []
def push(self,item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[-1]
def size(self):
return len(self.items)
def parchecker(parStr):#检查括号是否匹配的函数
s=Stack()
balanced = True
index=0
while index < len(parStr) and balanced:
#使用while循环配合index递加进行遍历,index和len的细节要注意
#也可使用for in 循环与break(未完全遍历就匹配失败) 组合
par=parStr[index]
if par in "([{": #这里是细节,注意要判断是否是三个符号中的一个
s.push(par)
else:
if not s.isEmpty():
topToken = s.pop() #从栈顶从栈顶pop出最新的左括号
if match(topToken,par):#判断两括号格式是否匹配
balanced = True
else:
balanced=False
return False #左右括号格式不同,匹配失败
else:
balanced = False #匹配失败,右括号多了
index+=1
if s.isEmpty() and balanced:
return True
else:
return False #匹配失败,左括号多了
def match(str1,str2): #判断两括号格式是否匹配的函数
ls1=["(","[","{"]
ls2=[")","]","}"]
return ls1.index(str1)==ls2.index(str2)
print(parchecker(input()))
1.特别要注意的是如果使用条件语句if,else,一定要完全穷尽所有情况,不然测试样例会出错。之前我在判断par是否是“)]}”,用了elif 语句,没有完全穷尽,测试样例一直出错。
2.在扫描到右括号时,我在栈为空的情况中,False没有大写,测试样例也会出错,可以直接return False,也可用balanced=False。
程序流程:
2一维开心消消乐(10分)题目内容:开心消消乐我们都熟悉,我们可以用刚学过的栈来做一个“一维”的开心消消乐游戏,这个游戏输入一串字符,逐个消去相邻的相同字符对。如果字符全部被消完,则输出不带引号的“None”
输入格式:
一个字符串,可能带有相邻的相同字符,如“aabbbc”
输出格式:
一个字符串,消去了相邻的成对字符,如“bc”
输入样例1:
beepooxxxyz
输出样例1:
bpxyz
输入样例2:
kxkx
输出样例2:
kxkx
输入样例3:(这里bb被消了以后,第二个a挨上来了,所以两个a也相邻,同样消去)
abbacddccc00
输出样例3:
None
解题思路:
1.先创建栈
2.从左往右遍历字符串,如果栈不空,则将当前所遍历的字符串与栈顶元素进行比较:
如果相同,则把栈顶元素pop出来(相当于消除)
如果不同,把当前所遍历的字符入栈(相当于不消除)
3.将最终的栈转化为字符串输出,如果栈空了,就输出None
#一维开心消消乐
class Stack:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[-1]
def size(self):
return len(self.items)
def popFun(inputstr):
st=Stack()
for a in inputstr:
if not st.isEmpty() and a==st.peek():
st.pop()
else:
st.push(a)
if st.isEmpty():
print("None")
else:
print("".join(st.item))
popFun(input())
3强迫症老板和他的洗碗工(10分)题目内容:洗碗工小明碰上了一位强迫症老板老王,餐厅一共就10只盘子,老板给仔细编上了0~9等10个号码,并要求小明按照从0到9的编号来洗盘子,当然,每洗好一只盘子,就必须得整齐叠放起来。
小明洗盘子期间,经常就有顾客来取盘子,当然每位顾客只能从盘子堆最上面取1只盘子离开。
老王在收银台仔细地记录了顾客依次取到盘子的编号,比如“1043257689”,这样他就能判断小明是不是遵照命令按照0123456789的次序来洗盘子了。
你也能像老王一样作出准确的判断吗?
输入格式:
长度为10的字符串,其中只包含0~9的数字,且不重复,代表顾客依次取到的盘子编号
输出格式:
字符串:Yes或者No,表示遵照次序洗盘子,或者没有遵照次序洗盘子
输入样例1:
1043257689
输出样例1:
Yes
输入样例2:
4230178956
输出样例2:
No
问题分析:
小明按照从0到9的编号来洗盘子,洗好一只盘子,就放在旁边,接下来洗好的盘子,会放在刚才洗好的盘子上面。
顾客只能从洗好的盘子堆的顶部拿盘子。这和栈的结构很相似,只能从栈顶压入元素,取元素也只能从栈顶来取。
用栈来模拟洗好的盘子堆,三种情况:
1.全部盘子洗好后,已洗好的盘子堆的顺序应该是:
[ 9,8,7,6,5,4,3,2,1,0 ]
顾客也只能按照这个顺序拿。
2.洗好一个盘子,顾客拿一个盘子,顾客拿的顺序应该为:
[ 0,1,2,3,4,5,6,7,8,9 ]
3.中间状态:
eg.洗好了3个盘子放在盘子堆,顾客拿了1个,接下来又洗了一个:
那么已洗好的盘子堆顺序应该为:[ 0,1,3]
顾客应该拿了2号盘子
我们可以抽象出一条不变的性质:
顾客从已洗好的盘子堆中拿到的盘子如果是是大号,那么盘子堆中从0号到这个盘子之间的顺序都应该固定了。
eg: 顾客取了6号盘子,那么盘子堆的顺序应该为:
[ 0,1,2,3,4,5,6 ]
不然他取不到6号盘子
解题思路:
我们用栈来模拟洗盘子,取盘子的过程。
这个过程模拟下来,如果按照取盘子的顺序,推不回正确的洗盘子的顺序,就说明小明没有按照规定洗盘子。
class Stack:
def __init__(self):
self.items=[]
def isEmpty(self):
return self.items==[]
def push(self,item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[-1]
def size(self):
return len(self.items)
s=input() #顾客取盘子的次序
st=Stack()
i=0 #用作顾客取盘子顺序的索引
n=0 #假设小明正在洗第一个盘子
while n<10 and i<10: #模拟过程,当洗盘子或者取盘子到10 次之后,停止模拟
#洗盘子
k=int(s[i]) #顾客取的盘子的编号
if n<=k:
#如果当前洗的盘子比取到的盘子编号小,那么从当前洗的盘子到顾客取的盘子都应该是洗过的(进过栈了)
for dish in range(n,k+1):
st.push(dish)
n=k+1#并且下一个要洗的盘子应该是K+1,重新修改n的值
#取盘子
while not st.isEmpty() and st.peek()==int(s[i]):
#当栈不为空,并且栈顶盘子和顾客当前取到的盘子编号一样,就从栈顶移除,否则不移除。
m=st.pop()
i+=1
if st.isEmpty():
print("yes")
else:
print("no")
另外记录一下:如果用栈继承list类的方式定义栈,pop的时候会出错,不知道为什么,到学校再问同学:
class Stack(list):
def isEmpty(self):
return self==[]
def push(self,item):
self.append(item)
def pop(self):
return self.pop()
def peek(self):
return self[-1]
def size(self):
return len(self)
Python给的消息:
RecursionError: maximum recursion depth exceeded
12: def pop(self):
–>13: return self.pop()
self: [0, 1]