Leetcode 32:最長有效括號(最詳細的解法!!!)
阿新 • • 發佈:2018-11-19
給定一個只包含 '('
和 ')'
的字串,找出最長的包含有效括號的子串的長度。
示例 1:
輸入: "(()"
輸出: 2
解釋: 最長有效括號子串為 "()"
示例 2:
輸入: ")()())"
輸出: 4
解釋: 最長有效括號子串為 "()()"
解題思路
這種問題我們首先想到的解決思路是通過棧。我們首先遍歷一遍s
,判斷遍歷到的字元ch
是不是(
,如果是的話,我們就將ch.index
加入到棧中,例如
( ( )
↑
stack: 0
如果遍歷到的元素是)
,且棧不為空棧頂元素是(
,我們就出棧。
( ( )
↑
stack: 0
否則如果棧為空,我們就將ch.index
stack: | 0 3 7 13 |
-1 len(s)
此時我們只要遍歷stack
,找到兩兩元素之間隔最大的距離即可。
class Solution:
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
s_len, stack = len(s), list()
for i, ch in enumerate (s):
if ch == '(':
stack.append(i)
elif stack and s[stack[-1]] == '(':
stack.pop()
else:
stack.append(i)
if not stack:
return s_len
stack = [-1] + stack + [s_len]
for i,val in enumerate (stack[1:]):
stack[i] = val - stack[i] - 1
return max(stack[:-1])
這個問題也可以通過動態規劃來做,而且思路也非常清晰。我們定義
表示當前位置i
結尾的最長有效括號的長度,那麼
稍微說明一下,因為
為此時的最大長度,那麼i-1-f(i)
就表示之前還未匹配的(
,例如
( ) ( ( ) )
↑ i
如果我們的i
在這個位置,那麼i-1-f(i)
就是箭頭所指的位置。由於此時箭頭所指的位置是(
,所以我們應該將f(i)+2=4
。但是我們此時得到只是一個小區間內的最大值,我們應該還要加上以箭頭前一位置結尾的最大長度,那麼此時我們得到的解過就是以i
結尾的最大長度。
最後這個演算法還有一個小問題,如果我們此時i
是(
怎麼辦?我們上面的f(i)+2
就是錯誤的。所以我們乾脆不考慮這種情況,只考慮)
即可。那麼只考慮)
情況是合理的嗎?合理,因為最長有效括號一定是以)
結尾。
class Solution:
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
s_len, result = len(s), 0
if s_len < 2:
return 0
mem = [0]*s_len
for i in range(1, s_len):
if s[i] == ')':
left = i-1-mem[i-1]
if left >= 0 and s[left] == '(':
mem[i] = mem[i-1] + 2
mem[i] += mem[i-mem[i]]
result = max(result, mem[i])
return result
reference:
https://leetcode.com/problems/longest-valid-parentheses/discuss/14126/My-O(n)-solution-using-a-stack
我將該問題的其他語言版本新增到了我的GitHub Leetcode
如有問題,希望大家指出!!!