数据结构与算法Python版——第三周作业

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]

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值