• Python学习记录:括号配对检测问题


    Python学习记录:括号配对检测问题

    、问题描述

    在练习Python程序题的时候,我遇到了括号配对检测问题。

    问题描述:提示用户输入一行字符串,其中可能包括小括号 (),请检查小括号是否配对正确,配对成功与否分别输出:

     

    配对成功!

    配对失败!

     

    其中,小括号配对要考虑配对顺序,即()表示配对,)(不是配对,只考虑小括号配对。

     

    一提起括号配对,我们可能会想到C语言正则表达式计算的符号优先级问题,在C语言中我们通常使用栈来解决,而在Python中我们也可以用栈的思路和方法,以列表的形式来实现它。把list当做栈来使用,但建立的还是list对象,提供的是list类型的函数方法。

    Python列表函数&方法

    序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字——它的位置,或索引,第一个索引是0,第二个索引是1,依此类推。

    Python6个序列的内置类型,但最常见的是列表和元组。

    序列都可以进行的操作包括索引,切片,加,乘,检查成员。

    此外,Python已经内置确定序列的长度以及确定最大和最小的元素的方法。

    列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现。

    列表的数据项不需要具有相同的类型

     

    创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可。如下所示:

    list1 = ['physics', 'chemistry', 1997, 2000]
    
    list2 = [1, 2, 3, 4, 5 ]
    
    list3 = ["a", "b", "c", "d"]

     

    与字符串的索引一样,列表索引从0开始。列表可以进行截取、组合等。

     

    1.Python包含以下函数:

    1cmp(list1, list2):比较两个列表的元素

    2len(list):列表元素个数

    3max(list):返回列表元素最大值

    4min(list):返回列表元素最小值

    5list(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包含以下方法:

    1list.append(obj):在列表末尾添加新的对象

    2list.count(obj):统计某个元素在列表中出现的次数

    3list.extend(seq):在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)

    4list.index(obj):从列表中找出某个值第一个匹配项的索引位置

    5list.insert(index, obj):将对象插入列表

    6list.pop([index=-1]):移除列表中的一个元素(默认最后一个元素),并且返回该元素的值

    7list.remove(obj):移除列表中某个值的第一个匹配项

    8list.reverse():反向列表中元素

    9list.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

  • 相关阅读:
    XML中对于一个books.xml的详情显示,删除按钮,修改并保存按钮 和 添加按钮。完成这些按钮所对应的功能(XmlDocument)。
    如何写一个验证码
    Binary Search
    数据库排行榜
    mac os 下 sublime text 2 和 iterm2 便捷配置
    HttpGet,HttpPost,HttpPut,HttpDelete
    Compile C/C++ In Eclipse for Android
    To Use EGit(Git for Eclipse)
    Android NDK about Library (static library , share library and 3rd party library)
    Dealing with bitmap object in android NDK
  • 原文地址:https://www.cnblogs.com/BIXIABUMO/p/11627342.html
Copyright © 2020-2023  润新知