Go 返回最长有效子串长度
以下是几种在 Go 中实现查找最长有效括号子串长度的方法:
方法一:动态规划
go
func longestValidParentheses(s string) int {
n := len(s)
if n == 0 {
return 0
}
dp := make([]int, n)
maxLen := 0
for i := 1; i < n; i++ {
if s[i] == ')' {
if s[i-1] == '(' {
if i >= 2 {
dp[i] = dp[i-2] + 2
} else {
dp[i] = 2
}
} else {
prev := i - dp[i-1] - 1
if prev >= 0 && s[prev] == '(' {
dp[i] = dp[i-1] + 2
if prev > 0 {
dp[i] += dp[prev-1]
}
}
}
if dp[i] > maxLen {
maxLen = dp[i]
}
}
}
return maxLen
}
方法二:栈
go
func longestValidParentheses(s string) int {
maxLen := 0
stack := []int{-1} // 初始化栈底元素
for i, char := range s {
if char == '(' {
stack = append(stack, i)
} else {
stack = stack[:len(stack)-1] // 弹出栈顶元素
if len(stack) == 0 {
stack = append(stack, i) // 记录新的基准点
} else {
currentLen := i - stack[len(stack)-1]
if currentLen > maxLen {
maxLen = currentLen
}
}
}
}
return maxLen
}
方法三:双向遍历(最优空间复杂度)
go
func longestValidParentheses(s string) int {
left, right, maxLen := 0, 0, 0
// 从左到右遍历
for i := 0; i < len(s); i++ {
if s[i] == '(' {
left++
} else {
right++
}
if left == right {
if 2*right > maxLen {
maxLen = 2 * right
}
} else if right > left {
left, right = 0, 0
}
}
left, right = 0, 0
// 从右到左遍历
for i := len(s) - 1; i >= 0; i-- {
if s[i] == '(' {
left++
} else {
right++
}
if left == right {
if 2*left > maxLen {
maxLen = 2 * left
}
} else if left > right {
left, right = 0, 0
}
}
return maxLen
}
使用示例
go
package main
import "fmt"
func main() {
fmt.Println(longestValidParentheses("(()")) // 输出: 2
fmt.Println(longestValidParentheses(")()())")) // 输出: 4
fmt.Println(longestValidParentheses("")) // 输出: 0
fmt.Println(longestValidParentheses("()(()")) // 输出: 2
fmt.Println(longestValidParentheses("()(())")) // 输出: 6
}
方法比较
-
动态规划:
- 时间复杂度:O(n)
- 空间复杂度:O(n)
- 优点:直观易懂,容易实现
- 缺点:需要额外的数组空间
-
栈:
- 时间复杂度:O(n)
- 空间复杂度:O(n)
- 优点:思路清晰,利用栈的特性
- 缺点:同样需要额外空间
-
双向遍历:
- 时间复杂度:O(n)
- 空间复杂度:O(1)
- 优点:空间效率最高
- 缺点:需要两次遍历
这些方法都能有效解决最长有效括号子串长度的问题,可以根据具体需求选择合适的方法。