先來看下題目:
給你一個只包含 '('
和 ')'
的字符串,找出最長有效(格式正確且連續)括號子串的長度。
示例 1:
輸入:s = "(()"
輸出:2
解釋:最長有效括號子串是 "()"
示例 2:
輸入:s = ")()())"
輸出:4
解釋:最長有效括號子串是 "()()"
示例 3:
輸入:s = ""
輸出:0
來源:力扣(LeetCode)
鏈接:https://leetcode.cn/problems/longest-valid-parentheses
上面這道題很多人用動態規劃來做【不過自己這裡太笨了,沒做出來】。參考了另一位大佬的做法,他是用了一個mask,用來記錄括號是否匹配,將不匹配的地方全部置為1,最後就轉化成了求這個mask中連續0【滿足匹配】元素的長度。這裡我用python進行了實現,先附完整代碼:
class Solution:
def longestValidParentheses(self, s: str) -> int:
if s == "":
return 0
stack = []
mask = [0 for _ in range(len(s))]
left,Len, ans =0,0,0
for i in range(len(s)):
if s[i] == '(': # 如果是左括號就加入棧
stack.append(i)
else:
if stack == []:# 如果棧為空
mask[i] = 1
else: # 如果棧不為空,且為右括號,例如[(()] stack = [0,1,2]
stack.pop() # 右括號出棧[((] stack =[0,1]
while stack != []:
mask[stack[-1]] = 1 # 另無效的左括號為1
stack.pop() # stack = [0] [(]
for i in range(len(s)):
if mask[i]:
Len = 0
continue
Len += 1
ans = max(ans,Len)
return ans
步驟:
1.如果s="",也就是輸入為空,直接返回0
2.創造一個與字符串s長度一樣的mask列表,並初始化為0,同時stack為棧,用來存儲括號
3.for遍歷s,然後有兩個情況需要判斷一下,第一種就是s的第一個元素是左括號"(",第二種就是第一個元素為右括號”)“。
第一種,如果遇到左括號"(",入棧stack.append(i)【這裡放入的是下角標】。
如果第一個元素不是左括號【也就是第一個元素是右括號】,那麼剛開始的stack沒有左括號入棧,也就是剛開始是空,則mask對應的第一個角標位置為1,表示無效的匹配。
如果stack不為空【表示第一次for循環有”(“入棧】且是右括號,匹配成功,那麼就執行stack.pop(),將這個右括號")"彈出。【彈出就只剩下左括號繼續和後面的匹配】
4.通過上面的for循環匹配過濾多余或者說無效的右括號,還遺留了一個問題,那就是可能會有多余的左括號,因此需要將多余的左括號標記出來,所以我們可以用stack[-1]獲得棧最上面的左括號的角標【C++中就是stack.top()】,每標記一次的同時,並將這個多余的也就是棧最上面的左括號彈出。在mask中標記出來並令其為1;【也就是代碼中的mask[stack[-1]]】,直到stack為空的時候結束循環,這樣我們就得到一個完整mask模板,它清楚的記錄了記錄了有效括號的下角標。
5.獲得mask中連續0最長的長度即可