May 04, 2020
https://leetcode-cn.com/problems/longest-valid-parentheses/
func longestValidParentheses(s string) int {
var stack []int
var lastStart, maxLen int
for i, item := range s {
if string(item) == "(" {
stack = append(stack, i)
} else {
if len(stack) > 0 {
stack = stack[:len(stack) - 1]
var length int
if len(stack) == 0 {
length = i - lastStart + 1
} else {
length = i - stack[len(stack) - 1]
}
if length > maxLen {
maxLen = length
}
} else {
lastStart = i + 1
}
}
}
return maxLen
}
括号的匹配,立马就会想到出栈入栈的过程,遇到 ”(” 入栈,遇到 ”)” 出栈。当栈为空时,遇到 ”)“,是势必无法匹配出栈的,因此这种情况我们需要从这里断开,前面匹配的结果,与后面的匹配情况已经无关了(因为已经不满足连续的条件了),重新开始新的入栈、出栈操作。
再来想下正常匹配的情况,正常匹配意味着会有一个 ”(” 出栈,则这段正常匹配的字符串的长度,可以通过出栈后新的栈顶的 ”(” 在字符串 s 中所处的位置离当前最后一个 ”)” 的距离得出。比如 ”(()“,栈应该是这样的 —— [”(”, ”(”],遇到 ”)” 后,栈顶的 ”(” 出栈,栈变成了 [”(”],而此时栈中的栈顶元素对应 s 中的索引为 0 的元素,此时 ”)” 的索引为 2,则字符串的长度可以计算得出 2 - 0 = 2。
还有一种情况,当最后一个 ”(” 也匹配出栈了,我们怎么计算字符串的长度呢?这里我定义了一个 lastStart 来表示本次栈匹配的开始位置(中间可能中断过)。当栈为空后,字符串的长度可以通过当前 ”)” 的位置,与本次匹配的起始位置的距离计算得出。
每次将长度进行比较,留下较大的值,最终得到的就是最长的子串。
痕迹
没有过去,就没法认定现在的自己