一、有效的括號(hào)
此題在《??數(shù)據(jù)結(jié)構(gòu)與算法——棧與隊(duì)列??》中出現(xiàn)
二、括號(hào)生成
此題在《??數(shù)據(jù)結(jié)構(gòu)與算法——廣度優(yōu)先與深度優(yōu)先搜索??》中出現(xiàn)
三、最長(zhǎng)有效括號(hào)
此題為leetcode??第32題??
思路:考慮使用動(dòng)態(tài)規(guī)劃,定義狀態(tài)dp[i]為以第i個(gè)元素結(jié)尾的最長(zhǎng)有效括號(hào)的長(zhǎng)度。有效的括號(hào)一定是以“)”結(jié)尾的,因此我們只需考察以“)”的字符,狀態(tài)轉(zhuǎn)移方程如下圖所示。注意dp的邊界條件,圖中并沒(méi)有體現(xiàn)出來(lái)。
class Solution:
def longestValidParentheses(self, s: str) -> int:
n = len(s)
dp = [0] * n
res = 0
for i in range(1, n):
if s[i] == ')':
if s[i - 1] == '(' and i - 2 >= 0:
dp[i] = dp[i - 2] + 2
elif i - dp[i - 1] - 1 >= 0 and s[i - dp[i - 1] - 1] == '(': # s[i - 1] == ')'
if i - dp[i - 1] - 2 >= 0:
dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2
else:
dp[i] = dp[i - 1] + 2
res = max(res, dp[i])
return res
四、刪除無(wú)效的括號(hào)
此題為leetcode??第301題??
思路:可以使用DFS和BFS兩種方式。(1)DFS,首先需要知道要?jiǎng)h除幾個(gè)左括號(hào)和右括號(hào),分別記為cntleft和cntright,挨個(gè)遍歷,除了能配對(duì)的,統(tǒng)計(jì)剩下的左右括號(hào)個(gè)數(shù)。然后在原始字符串上面進(jìn)行刪除操作,遍歷刪除的字符位置[0, len(s)-1], 對(duì)應(yīng)字符為左右括號(hào)時(shí),分別遞歸;當(dāng)前刪除位置需要傳遞給下一次遞歸,因?yàn)槊看蝿h除一個(gè)字符后,字符串長(zhǎng)度是減少1的,而刪除的位置正好是下一次迭代中開(kāi)始刪除的首位。是在循環(huán)刪除的時(shí)候,如果下一個(gè)字符和上一次回溯結(jié)束后的字符一樣時(shí),不需要再重復(fù)處理。當(dāng)cntleft和cntright都為0時(shí),檢查字符串s是否有效。(2)BFS,從刪除一個(gè)括號(hào)開(kāi)始枚舉,依次刪除2個(gè)括號(hào)、3個(gè)括號(hào)等等,分別為level 1、level 2、level 3等等。如果有某一層能有一個(gè)及以上的字符串合法,那么所有合法的字符串即為答案,不用在繼續(xù)下去,因?yàn)橐呀?jīng)滿足了“刪除最小數(shù)量的括號(hào)”的要求。
# DFS
class Solution:
def removeInvalidParentheses(self, s: str) -> List[str]:
# 確定有幾個(gè)多余的括號(hào)
cntleft, cntright = 0, 0
for c in s:
if c == '(':
cntleft += 1
if cntleft > 0 and c == ')':
cntleft -= 1
elif cntleft == 0 and c == ')':
cntright += 1
self.res = []
self.dfs(s, 0, cntleft, cntright)
return self.res
def is_valid(self, s):
count = 0
for c in s:
if c == '(':
count += 1
if c == ')':
count -= 1
if count < 0:
return False
return count == 0
def dfs(self, s, start, cntleft, cntright):
if cntleft == 0 and cntright == 0 and self.is_valid(s):
self.res.append(s)
for i in range(start, len(s)):
# 如果相鄰的兩個(gè)字符相同,那么只刪除一個(gè)就行
if i > start and s[i] == s[i - 1]:
continue
if s[i] == '(' and cntleft > 0:
self.dfs(s[:i] + s[i+1:], i, cntleft - 1, cntright)
if s[i] == ')' and cntright > 0:
self.dfs(s[:i] + s[i+1:], i, cntleft, cntright - 1)
# BFS
class Solution:
def removeInvalidParentheses(self, s: str) -> List[str]:
# 判斷括號(hào)是否合法
def is_valid(s):
count = 0
for c in s:
if c == '(':
count += 1
if c == ')':
count -= 1
if count < 0:
return False
return count == 0
# BFS
level = {s}
while True:
valid_level = list(filter(is_valid, level)) # 將level里合法的字符串篩選出來(lái)
if valid_level: # 如果level不為空則找到了結(jié)果
return valid_level
# 挨個(gè)進(jìn)入下一層
next_level = set() # 用set是為了去重
for item in level:
for i in range(len(item)):
if item[i] in '()': # 如果是括號(hào)就去掉
next_level.add(item[:i] + item[i + 1:])
level = next_level
本文摘自 :https://blog.51cto.com/u