Python学习记录:括号配对检测问题
Python学习记录:括号配对检测问题
一、问题描述
在练习Python程序题的时候,我遇到了括号配对检测问题。
问题描述:提示用户输入一行字符串,其中可能包括小括号 (),请检查小括号是否配对正确,配对成功与否分别输出:
配对成功!
配对失败!
其中,小括号配对要考虑配对顺序,即()表示配对,)(不是配对,只考虑小括号配对。
一提起括号配对,我们可能会想到C语言正则表达式计算的符号优先级问题,在C语言中我们通常使用栈来解决,而在Python中我们也可以用栈的思路和方法,以列表的形式来实现它。把list当做栈来使用,但建立的还是list对象,提供的是list类型的函数方法。
二、Python列表函数&方法
序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字——它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。
Python有6个序列的内置类型,但最常见的是列表和元组。
序列都可以进行的操作包括索引,切片,加,乘,检查成员。
此外,Python已经内置确定序列的长度以及确定最大和最小的元素的方法。
列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现。
列表的数据项不需要具有相同的类型。
创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。如下所示:
list1 = ['physics', 'chemistry', 1997, 2000] list2 = [1, 2, 3, 4, 5 ] list3 = ["a", "b", "c", "d"]
与字符串的索引一样,列表索引从0开始。列表可以进行截取、组合等。
1.Python包含以下函数:
1)cmp(list1, list2):比较两个列表的元素
2)len(list):列表元素个数
3)max(list):返回列表元素最大值
4)min(list):返回列表元素最小值
5)list(seq):将元组转换为列表
这里只介绍解决本问题相关的函数和方法,详情可参考:https://www.runoob.com/python/python-lists.html
①使用len()方法返回列表元素个数。
len()方法语法:
len(list)
返回列表元素个数。
以下实例展示了len()函数的使用方法:
list1, list2 = [123, 'xyz', 'zara'], [456, 'abc'] print("First list length : ",len(list1)) print("Second list length : ",len(list2))
输出结果如下:
②list()方法用于将元组转换为列表。
list()方法语法:
list(tup)
返回列表。
注:元组与列表是非常类似的,区别在于元组的元素值不能修改,元组是放在括号中,列表是放于方括号中。
以下实例展示了list()函数的使用方法:
aTuple = (123, 'xyz', 'zara', 'abc') aList = list(aTuple) print("列表元素:", aList)
输出结果如下:
2.Python包含以下方法:
1)list.append(obj):在列表末尾添加新的对象
2)list.count(obj):统计某个元素在列表中出现的次数
3)list.extend(seq):在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
4)list.index(obj):从列表中找出某个值第一个匹配项的索引位置
5)list.insert(index, obj):将对象插入列表
6)list.pop([index=-1]):移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
7)list.remove(obj):移除列表中某个值的第一个匹配项
8)list.reverse():反向列表中元素
9)list.sort(cmp=None, key=None, reverse=False):对原列表进行排序
①append()方法用于在列表末尾添加新的对象。
append()方法语法:
list.append(obj)
该方法无返回值,但是会修改原来的列表。
以下实例展示了append()函数的使用方法:
aList = [123, 'xyz', 'zara', 'abc'] aList.append(2009) print("Updated List : ", aList)
输出结果如下:
②pop()函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。
pop()方法语法:
list.pop([index=-1])
obj -- 可选参数,要移除列表元素的索引值,不能超过列表总长度,默认为 index=-1,删除最后一个列表值。
该方法返回从列表中移除的元素对象。
以下实例展示了 pop()函数的使用方法:
list1 = ['Google', 'Runoob', 'Taobao'] list_pop = list1.pop(1) print("删除的项为 :", list_pop) print("列表现在为 :", list1)
输出结果如下:
三、代码实现
代码实现如下:
#使用列表来存放栈元素 def parentheses(m): list1=[] for i in range(len(m)): if m[i]=='(' or m[i]==')': list1.append(m[i]) #将小括号元素放在list1 list2=[] #存放(,相当于栈 if len(list1)==0: #无小括号元素 return True elif list1[0]==')': #第一个元素为),即)在(前面 return False elif len(list1)%2!=0: #小括号元素总数为奇数,无论怎么配对也不会成功 return False else: for i in range(len(list1)): if list1[i]=='(': #将左括号元素放在list2 list2.append(list1[i]) elif list1[i]==')' and len(list2)!=0: #排除右括号比左括号多的情况 list2.pop() #只要list1中有一个右括号且list2中左括号个数不为0,就移除list2里的一个左括号,以此进行左右括号配对 else: return False return True m=input('请输入字符串:') if parentheses(m): print('括号配对成功!') else: print('括号配对失败!')
运行结果:
上面的程序可以正常运行,但我发现了新的问题:以上代码并不适用于所有可能的输入,比如我输入(((()),即左括号比右括号多的情况,程序运行结果却未报错。
经查阅,我发现网上关于Python括号配对的问题基本上都是利用列表方法实现,但关于不合理输入的异常处理情况考虑的比较少。这里列出了一些有代表性的可能的输入情况,并且对每一种输入情况进行处理,符合括号配对原则的配对成功,否则失败。
可能存在情况:((())).(((()).(()))).()()等等。
可以看到,当左括号比右括号多时,上面的代码无法处理异常。这里我用自己的思路对上面的代码进行修改,修改后的代码如下:
#使用列表来存放栈元素 def bracketsmatch(m): list1=[] left=[]#存放(,相当于栈 right=[]#存放),相当于栈 for i in range(len(m)): if m[i]=='(' or m[i]==')': list1.append(m[i])#将小括号元素放在list1 if len(list1)==0:#无小括号元素 return True elif list1[0]==')':#第一个元素为),即)在(前面 return False elif len(list1)%2!=0:#小括号元素总数为奇数,无论怎么配对也不会成功 return False else: for i in range(len(list1)): if list1[i]=='(': left.append(list1[i])#将左括号元素放在left elif list1[i]==')' and len(left)!=0:#排除右括号比左括号多的情况
right.append(list1[i])#将右括号元素放在right left.pop()#只要有一个右括号进入right,就将其移除,同时移除left里的一个左括号,以此进行左右括号配对 right.pop() if len(left)==0 and len(right)==0:#如果左右括号配对完毕 return True else:#左右括号未配对完毕,继续执行循环 continue else: return False m=input('请输入字符串:') if bracketsmatch(m): print('括号配对成功!') else: print('括号配对失败!')
运行结果:
修改后的代码虽然处理了左括号比右括号多时的异常情况,但又无法处理右括号比左括号多的情况。这也是让我有点头疼的一点,即使我知道是程序算法设计的问题,但由于时间问题,我没来得及再进一步深入解决这个问题,后续时间里我会继续思考,争取将这个缺口补上。
--------------------------------------------这里是时隔许久的分割线-----------------------------------------------------
非常感谢评论指正,我重新修改了上面的代码。
#使用列表来存放栈元素
def parentheses(m):
list1=[]
for i in range(len(m)):
if m[i]=='(' or m[i]==')':
list1.append(m[i]) #将小括号元素放在list1
list2=[] #存放(,相当于栈 if len(list1)==0: #无小括号元素
return True
elif list1[0]==')': #第一个元素为),即)在(前面
return False
elif len(list1)%2!=0: #小括号元素总数为奇数,无论怎么配对也不会成功
return False
else:
for i in range(len(list1)):
if list1[i]=='(': #将左括号元素放在list2
list2.append(list1[i])
elif list1[i]==')' and len(list2)!=0: #排除右括号比左括号多的情况
list2.pop() #只要list1中有一个右括号且list2中左括号个数不为0,就移除list2里的一个左括号,以此进行左右括号配对
else:
return False
#排除左括号比右括号多的情况
if len(list2)==0:
return True
else:
return False m=input('请输入字符串:')
if parentheses(m):
print('括号配对成功!')
else:
print('括号配对失败!')
运行结果:
可以看到,代码上只在最后添加了几行用来判断list2中是否有多余的左括号,整体解决了左括号比右括号多和右括号比左括号多的情况,经评论指正后发现正是这个细节导致了最终结果的输出,这也说明当时我考虑的角度很不全面,解决这个问题的过程中我获益良多。
参考资料:
https://www.runoob.com/python/python-lists.html
https://www.cnblogs.com/WoLykos/p/8709937.html
Python学习记录:括号配对检测问题的更多相关文章
- Python学习记录day8
目录 Python学习记录day8 1. 静态方法 2. 类方法 3. 属性方法 4. 类的特殊成员方法 4.1 __doc__表示类的描述信息 4.2 __module__ 和 __class__ ...
- Python学习记录day6
title: Python学习记录day6 tags: python author: Chinge Yang date: 2016-12-03 --- Python学习记录day6 @(学习)[pyt ...
- Python学习记录day5
title: Python学习记录day5 tags: python author: Chinge Yang date: 2016-11-26 --- 1.多层装饰器 多层装饰器的原理是,装饰器装饰函 ...
- Python学习记录day7
目录 Python学习记录day7 1. 面向过程 VS 面向对象 编程范式 2. 面向对象特性 3. 类的定义.构造函数和公有属性 4. 类的析构函数 5. 类的继承 6. 经典类vs新式类 7. ...
- 括号配对检测 A
括号配对检测 A ...
- 实验楼Python学习记录_挑战字符串操作
自我学习记录 Python3 挑战实验 -- 字符串操作 目标 在/home/shiyanlou/Code创建一个 名为 FindDigits.py 的Python 脚本,请读取一串字符串并且把其中所 ...
- 我的Python学习记录
Python日期时间处理:time模块.datetime模块 Python提供了两个标准日期时间处理模块:--time.datetime模块. 那么,这两个模块的功能有什么相同和共同之处呢? 一般来说 ...
- Python学习记录1-基础知识
基础知识 基础 #简单记录了部分基础知识 #普通的打印字符串 >>> print("hello world") hello world ------------- ...
- Python 学习记录
记录一些 学习python 的过程 -------------------------------------- 1. 初始学习 @2013年10月6日 今天开始学习python 了 遇到好多困难但是 ...
随机推荐
- Spring 框架下的 JDBC
Spring JDBC Spring 对JDBC技术规范做了进一步封装,它又叫Spring JDBCTemplate(jdbc模板技术) 纯JDBC:代码清晰的.效率最高.代码是最烦的. Spr ...
- 简单使用vue-cli
上一篇我们简单的看了看vue的基本用法,就是三步,首先就是用<script>标签引入vue的依赖,然后就是写html标签,在标签中用vue指令绑定一些属性,最后就是new Vue(xxx) ...
- Docker系列03-容器Docker镜像的使用
Docker镜像的使用前两个章节,介绍了容器的相关基础知识,这章我们介绍镜像的简单使用,镜像hub里面有来自于全世界贡献的各种镜像,包括一些入门和学习练手的镜像,今天我们使用的正式其中一个用于学习练习 ...
- 闲话复数(1) | 不现实的虚数 i 为什么虚?它长成什么样?
原文 | https://mp.weixin.qq.com/s/y-Nb3S508UZuf_0GtRuNaQ 复数的英文是complex number,直译是复杂的数.最早接触复数大概是在高中时期,只 ...
- Python selenium登录163邮箱示例
思路:使用python自带的unittest单元测试框架测试163邮箱登录成功的case import unittestfrom selenium import webdriverimport tim ...
- 浅谈python面向对象编程和面向过程编程的区别
面向过程:分析出解决问题所需要的步骤,然后用函数把这些步骤一步步实现,使用的时候再一个个的依次调用即可. 优点:性能高 缺点:相较于面向对象而言,不易维护,不易复用,不易扩展 适合于小型的项目面向对象 ...
- PDF软件
推荐的PDF阅读软件:文电通
- CH-0304 IncDec Sequence
0304 IncDec Sequence 0x00「基本算法」例题 描述 给定一个长度为 n(n≤10^5 ) 的数列 {a_1,a_2,…,a_n},每次可以选择一个区间 [l,r],使下标在这个区 ...
- JAVA笔记 -- 访问权限控制
访问权限控制 没有权限控制的时候,由于所有的接口都是可以访问的.当一个类库部分代码,发现有更好的方法解决的时候,可能其他接口会发生改动.这会导致另一个地方的引用该类库的程序发生崩溃.为了解决这种问题, ...
- 利用Azure虚拟机安装Dynamics 365 Customer Engagement之九:新建组织
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...