
1.遇到括号就想用栈,初步想法是只使用top指针来模拟栈,遇到'('就压入栈,遇到')'时,如果栈内有元素(即有剩余'(')就弹出栈,计数值+2;若没有元素,说明不是有效括号,计数值清零。最后记录最大的计数值就是答案。完整代码如下:
cpp
1. int longestValidParentheses(char* s) {
2. int top = 0;
3. int cnt = 0;
4. int res = 0;
5.
6. for (int i = 0; s[i] != '\0'; i++){
7. if (s[i] == '('){
8. top++;
9. } else {
10. if (top > 0){
11. top--;
12. cnt += 2;
13. res = fmax(res, cnt);
14. } else {
15. cnt = 0;
16. }
17. }
18. }
19.
20. return res;
21. }

可以看到,当前代码无法处理中间有'('作为隔断的情况,它将左右两个括号隔开了,连续最长有效括号应该是2而不是4。
2.正确的做法是设置一个栈,栈内放置括号下标,且栈底元素永远是上一个阻断的括号,称为哨兵括号。栈内首先需要将-1压入栈中充当哨兵下标,这样可以解决边界问题,且如果一开始就有一个完整括号的话(即下标0和1分别为'('和')'时,计算出的长度值恰好为2)。在遇到'('时正常压入栈,遇到')'时出栈,如果此时栈顶指针到底就说明本次遇到的')'没有匹配成功,它成为新的哨兵括号;否则就计算当前长度,此时top指向的是本次匹配上的'('的下标,它应该被弹出了,所以需要再-1指向当前新栈顶,此时的i - stacktop - 1才是长度值。
3.基于以上思想,可写出完整代码如下:
cpp
1. // 最长有效括号
2. int longestValidParentheses(char* s) {
3. int len = strlen(s);
4. if (len == 0) return 0;
5. int stack[len + 1]; // 栈保存下标,用于计算有效括号区间长度
6. int top = 0;
7. stack[top++] = -1; // 哨兵下标,作为有效区间的左边界基准
8. int res = 0; // 记录最长有效括号长度
9.
10. for (int i = 0; i < len; i++){
11. if (s[i] == '('){
12. // 左括号:把下标入栈
13. stack[top++] = i;
14. } else {
15. // 右括号:栈顶出栈
16. top--;
17. if (top == 0){
18. // 栈空,说明当前右括号无法匹配,更新哨兵到当前下标
19. stack[top++] = i;
20. } else {
21. // 栈不为空,当前i - 新栈顶即为当前有效括号长度
22. res = fmax(res, i - stack[top - 1]);
23. }
24. }
25. }
26. return res;
27. }
该算法时间复杂度和空间复杂度均为O(n)。