【Leetcode】32. Longest Valid Parentheses

题目地址:

https://leetcode.com/problems/longest-valid-parentheses/

给定一个括号序列 s s s,求其最长的合法括号子串的长度。

思路是用栈(此题还有一个比较好写的动态规划做法,参考https://blog.csdn.net/qq_46105170/article/details/108504436)。由于要计算合法的括号子串的长度,这里栈要存储下标而不是括号本身。

对于一个括号序列,从左到右遍历之。如果遇到左括号,就入栈;如果遇到右括号(下标是 j j j),此时如果栈不空,就将栈顶的左括号与之匹配(算法叙述完毕后将会知道右括号是不会入栈的,所以此处不考虑栈顶是右括号的情形),先将栈顶出栈,此时若栈非空且栈顶为 i i i,而 s [ i + 1 , . . . , j ] s[i+1,...,j] s[i+1,...,j]是合法的括号序列,所以用 j − i j-i ji更新最终答案;若栈空,此时栈并没有记录序列长度,所以要另外开一个变量start来存储合法序列的开头位置,然后用长度更新答案。这个start一开始设为 0 0 0,一旦遇到未匹配的右括号,就置为这个右括号的后一位即可。

算法正确性证明:对括号长度做归纳。当长度为 1 1 1或者 2 2 2的时候算法正确。考虑括号长度为 k k k的情况。如果遍历到的第一个括号是右括号,那这个括号不可能属于合法序列,此时start被更新为 1 1 1,接下来就是对长度 k − 1 k-1 k1的序列进行算法了,据归纳假设,如果未用start更新答案,则答案正确,若用到了start,由于start此时是 1 1 1,答案也是对的;如果遍历到的第一个括号是左括号,此时start 0 0 0,接下来就是在遍历长 k − 1 k-1 k1的序列,按照上面类似的推理也知道算法正确。

代码如下:

import java.util.ArrayDeque;
import java.util.Deque;

public class Solution {
    public int longestValidParentheses(String s) {
        if (s == null || s.isEmpty()) {
            return 0;
        }
        
        int res = 0;
        
        // 开一个栈存储括号的下标
        Deque<Integer> stack = new ArrayDeque<>();
        int start = 0;
    
        for (int i = 0; i < s.length(); i++) {
        	// 左括号直接入栈
            if (s.charAt(i) == '(') {
                stack.push(i);
            } else {
            	// 遇到右括号,如果栈空,说明该右括号要舍弃,不会成为合法序列的开头,将start置为i + 1
                if (stack.isEmpty()) {
                    start = i + 1;
                } else {
                	// 否则将栈内的左括号弹出来,这样栈顶到i这一段(不包括栈顶)的这一部分就是个合法的序列,更新res;
                	// 若栈空,则用start到i的这一段更新res
                    stack.pop();
                    if (stack.isEmpty()) {
                        res = Math.max(res, i - start + 1);
                    } else {
                        res = Math.max(res, i - stack.peek());
                    }
                }
            }
        }
        
        return res;
    }
}

时空复杂度 O ( n ) O(n) O(n)

也可以不用开start这个变量,而直接将无法匹配的右括号下标也入栈。代码如下:

import java.util.ArrayDeque;
import java.util.Deque;

public class Solution {
    public int longestValidParentheses(String s) {
        int res = 0;
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                stk.push(i);
            } else {
                if (!stk.isEmpty() && s.charAt(stk.peek()) == '(') {
                    stk.pop();
                    res = Math.max(res, i - (stk.isEmpty() ? -1 : stk.peek()));
                } else {
                    stk.push(i);
                }
            }
        }
        
        return res;
    }
}

时空复杂度一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值