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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM