Leetcode 32. Longest Valid Parentheses

32. Longest Valid Parentheses

题目

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

Example 1:

Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

Example 2:

Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"

解题思路

方法一:动态规划

(1)用L[i]表示以s[i]结尾的(必须包括s[i])的最长有效括号;

(2)初始时,L[0] = 0;

(3)状态转移方程:

  • 如果s[i] == ‘(’,则以s[i]结尾的序列必然不合法,因此L[i] = 0;
  • 如果s[i] == ‘)’,先找到L[i-1]的最长序列的前一位,下标j = i - 1 - L[i-1]。如果j < 0或者s[j] == ‘)’,说明L[i-1]的最长序列之前没有一个’(‘来与s[i]的’)'匹配,因此L[i] = 0; 如果j >= 0 且 s[j] == ‘(’,则s[j]和s[i]匹配,j与i之间串的长度为L[i-1] + 2,同时j与i之间的串还可以与L[j-1]的串相连(当j-1>=0时)。

(4)最后我们求得了以s中每个元素结尾的最长有效括号,选出最大的即可。

代码如下:

class Solution {
public:
	int longestValidParentheses(string s) {
		if (s.size() < 2) return 0;
		vector<int> L(s.size(), 0);
		int maxLen = 0;
		for (int i = 1; i < s.size(); i++) {
			int j = i - 1 - L[i-1];
			if (s[i] == '(' || j < 0 || s[j] == ')'){
				L[i] = 0;
			}
			else {
				L[i] = L[i-1] + 2;
				if (j - 1 >= 0) {
					L[i] += L[j-1];
				}
				if (L[i] > maxLen){
					maxLen = L[i];
				}
			}
		}
		return maxLen;
	}
};

方法二: 栈

用栈模拟括号的匹配,在遍历串s时,遇到’(‘时,将其下标入栈;遇到’)'时,将栈顶元素出栈,并计算当前匹配的括号的长度。

(1)将栈顶元素作为遍历过程中最后一个未匹配的括号的下标;

(2)初始时,栈顶元素为-1(因为从s下标从0开始,因此-1是初始时最后一个未匹配的括号的下标);

(3)遍历时,当遇到左括号,此时该左括号是最后一个未匹配的括号,因此将其下标入栈;

(4)当遇到右括号时,该右括号可以匹配栈顶下标对应的左括号,因此栈顶元素出栈。此时有两种情况:

  • 栈不为空:以该右括号结尾的最长有效括号的起点下标为出栈后栈顶元素+1(栈顶元素是最后一个未匹配的括号的下标),因此以该右括号结尾的最长有效括号的长度为该右括号下标减去栈顶元素值。
  • 栈为空:说明该右括号没有匹配左括号,该右括号是多出来的右括号,将其下标入栈作为栈顶元素(作为最后一个未匹配的括号的下标)。

(5)当遍历完串s后,我们得到了以s中每个右括号结尾的串的最长有效括号,选出最大的即可。

代码如下:

class Solution {
public:
	int longestValidParentheses(string s) {
		if (s.size() < 2) return 0;
		stack<int> st;
		st.push(-1);
		int maxLen = 0;
		for (int i = 0; i < s.size(); i++) {
			if (s[i] == '(') {
				st.push(i);
			}
			else {
				st.pop();
				if (st.empty()) {
					st.push(i);
				}
				else {
					maxLen = max(maxLen, i - st.top());
				}
			}
		}
		return maxLen;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值