Given a string containing just the characters ‘(’ and ‘)’, find the length of the longest valid (well-formed) parentheses substring.
Example 1:
Input: s = "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()".
Example 2:
Input: s = ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()".
Example 3:
Input: s = ""
Output: 0
题解
动态规划问题的思路都是从简单结果推导出复杂结果。
定义: 假设输入字符串为s,定义一个函数
f
(
i
)
f(i)
f(i)表示s前
i
i
i 位的子串中包含的最大合法括号长度。
已知: 前
i
−
1
i-1
i−1位的子串中最大合法括号长度为
f
(
i
−
1
)
f(i-1)
f(i−1)
引入变量: 在其末尾追加一个字符
s
[
i
]
s[i]
s[i],观察
s
[
i
]
s[i]
s[i]会对之前的结果造成什么影响。
发现规律: 很明显,只有当新字符串的最右边出现了一个更长的括号组合时才会影响之前的结果。
推论: 假设以字符
s
[
i
]
s[i]
s[i] 为结尾的最大合法括号长度为
g
(
i
)
g(i)
g(i),则当
f
(
i
−
1
)
<
g
(
i
)
f(i-1) < g(i)
f(i−1)<g(i) 时,
f
(
i
)
=
g
(
i
)
f(i) = g(i)
f(i)=g(i),否则
f
(
i
)
=
f
(
i
−
1
)
f(i) = f(i - 1)
f(i)=f(i−1)。
故可得到以下公式:
f
(
i
)
=
{
0
,
i
=
0
f
(
i
−
1
)
,
s
[
i
]
=
‘
(
’
m
a
x
(
f
(
i
−
1
)
,
g
(
i
)
)
,
s
[
i
]
=
‘
)
’
f(i)=\left\{ \begin{aligned} 0&,& i=0 \\ f(i-1)&, & s[i] = ‘(’ \\ max(f(i-1), g(i))&,& s[i]=‘)’ \end{aligned} \right.
f(i)=⎩
⎨
⎧0f(i−1)max(f(i−1),g(i)),,,i=0s[i]=‘(’s[i]=‘)’
得到公式后,剩下就是简单的编程了:
func longestValidParentheses(s string) int {
if len(s) == 0 {
return 0
}
validLen := make([]int, len(s))
var tailLvpLen int
for i := 0; i < len(s); i++ {
ch := s[i]
if i == 0 {
validLen[i] = 0
continue
}
validLen[i] = validLen[i-1]
if ch == ')' {
tailLvpLen = lengthOfTailLVP(s[:i+1])
if tailLvpLen > validLen[i-1] {
validLen[i] = tailLvpLen
}
}
}
return validLen[len(s)-1]
}
func lengthOfTailLVP(s string) int {
stack := make([]byte, 0)
length := 0
subLen := 0
for i := len(s) - 1; i >= 0; i-- {
ch := s[i]
if ch == '(' {
if len(stack) == 0 {
return length
}
if stack[len(stack)-1] == ')' {
stack = stack[:len(stack)-1]
subLen += 2
}
} else {
stack = append(stack, ch)
}
if len(stack) == 0 {
length += subLen
subLen = 0
}
}
return length
}