LeetCode题目:最长有效括号

题目描述:

给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子的长度。
示例 1:
输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”

示例 2:
输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

这道题最容易想到的就是暴力破解法,把输入字符串s里面的所有连续的子串都拿出来,判断这个子串是不是有效的,如果有效就判断其长度。当所有子串都被判断了一遍,一定会找到一个最长有效括号的长度。但是这个方法毫无疑问是比较耗时,如果输入的s很长的时候,摆脱不了执行超时的命运(至少我就尝试了很多遍超时),所以需要另寻出路。
之前在有做过一道题,判断输入的字符串是不是有效的括号。那道题里面用到了堆栈,遇到了左半边的括号就推进堆栈里,遇到右边的括号就推出堆栈里的内容,看是否能够和这个右半边的括号配对,如果能配对就继续执行,不能配对就直接返回配对失败了。
应用到这道题里面,可以创建一个堆栈,遇到 ‘(’ 时,就把当前 ‘(’ 的位置推进堆栈,当遇到 ‘)’ 时就弹出堆栈顶部的内容,前面一个 ‘(’ 就成功配对了,在还没读进下一个字符进行判断是,如今堆栈顶部的内容就是一个无效的括号(至少是目前位置是无效的),用当前的位置减去堆栈顶部的内容就能得到有效括号的长度了。同时,为了防止字符串的第一个字符是 ‘)’ ,在所有步骤之前在堆栈里放一个-1,防止执行pop()出错,同样的,当执行到一定的阶段的时候,有可能遇到 ‘)’ 比 ‘(’ 多,也就是说弹出的次数比推进的次数错,如果不采取措施一定会执行出错,所以在遇到 ‘)’ 弹出堆栈的内容是,判断堆栈是否为空,如果堆栈为空,则推进当前 ‘)’ 所在的位置(同时这个 ‘)’ 一定是无效的!!)。当遍历完字符串,一定会找出一个最长有效括号的长度。

代码(Java):

public class Solution {
	public static void main(String[] args) {
		String s = "(()";
//		System.out.println(s.charAt(s.length()-1));
		System.out.println(longestValidParentheses(s));
	}
	
	 public static int longestValidParentheses(String s) {
		int maxans = 0;  //存放最长有效括号的长度
        Stack<Integer> stack = new Stack<>();  //创建一个新的栈来处理,遍历字符串里面的字符,当遇到'('时,推进当前的位置,遇到')'时,弹出栈最顶的内容(与当前的')'配对),并推进当前位置的坐标
        									//这样有效的括号(成对)都是一进一出的,堆栈最顶部的内容就是找到最近一个无效(至少是还不确定有效)的括号,与当前的位置相减就得到有效括号长度
        stack.push(-1);  //首先往栈里推进一个-1,防止字符串的第一个字符就是')',堆栈为空,执行pop出错
        for (int i = 0; i < s.length(); i++) {  //遍历字符串里面的每一个字符
            if (s.charAt(i) == '(') {  //当遇到了'('时,推进当前的位置
                stack.push(i);
            } else {  //如果遇到')',推出栈最顶端的内容
                stack.pop();
                if (stack.empty()) {  //如果堆栈里是空的,则推进当前')'的位置,和一开始推进-1一样道理
                    stack.push(i);
                } else {
                    maxans = Math.max(maxans, i - stack.peek()); //目前位置最长的有效长度
                }
            }
        }
        return maxans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值