Leetcode——32. Longest Valid Parentheses

一、题目描述

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

For "(()", the longest valid parentheses substring is "()", which has length = 2.

Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.


给定一个字符串,只有字符'('和')',找到最长的有效匹配括号子串长度。


二、思路

思路一:栈实现

一般来说,括号匹配最容易想到的做法是栈,所以一开始采用了栈的做法。

思路是:如果只是求括号匹配,不需要连续,那直接使用栈的结构就可以匹配,遇到左括号入栈,遇到右括号就从栈中匹配推出一个左括号匹配即可。举个例子,s = (((()(((),这个字符串有两处括号匹配,但是本题要求的是最长子串,所以要求是连在一起的,所以上述字符串就只能算一处匹配,最长的长度是2.我采用的解决方法是定义一个布尔数组,数组大小和字符串长度一样,记录每一个位置是否匹配,然后到最后统计连续true的长度,就可以得到最长的匹配子串啦。算法描述如下:

声明一个栈st,一个布尔数组isMatch,循环遍历字符串s,循环遍历是i表示第i个字符:

1. 当遇到一个左括号时,将左括号所在的字符位置i入栈;

2. 否则,如果栈不为空,那弹出栈顶的值top,并把isMatch[top]和isMatch[i]置为true。

循环结束后,统计最长的连续1的个数。


这个思路是直接简单且快速的,然后我注意到的是这道题的tag是动态规划(DP),所以我考虑了一下动态规划的方法来解决这道题。


思路二:动态规划

动态规划解决的话,首先要定义子问题。子问题dp[i]表示第i个字符处的最长匹配子串的长度。作为一个最长的匹配子串,肯定是以')'结束,因此,所有以'('结束的位置的dp值直接都是0,只需要考虑以')'结束的情况。有两种情况:


1.当右括号之前是左括号,即()的情况:

当s[i] = ')'且s[i-1]是’(’,那么dp[i] = dp[i-2] + 2;


2.当右括号之前也是右括号,即))的情况,这有可能是(()),也可能是((()())):

s[i - dp[i-1] - 1]表示跳过前面已匹配好的位置,如果这个位置是’(’,那么

dp[i] = dp[i−1] + dp[i−dp[i−1]−2] + 2


三、代码

思路一代码:
int longestValidParentheses_stack(string s) {
	stack st;
	int res = 0;
	if (s.length() == 0)
		return 0;
	bool isMatch[s.length()];
	memset(isMatch, false, sizeof(isMatch));
	for (int i = 0; i < s.length(); i++) {
		if (s[i] == '(')
			st.push(i);
		else {
			if (!st.empty()) {
				isMatch[st.top()] = true;
				isMatch[i] = true;
				st.pop();
			}
		}
	}
	int temp = 0;
	for (int i = 0; i < s.length(); i++) {
		if (isMatch[i])
			temp++;
		else
			temp = 0;
		if (res < temp)
			res = temp;
	}
	return res;
}

思路二代码:
int longestValidParentheses_dp(string s) {
	int res = 0;
	int dp[s.length()];
	memset(dp, 0, sizeof(dp));
	for (int i = 1; i < s.length(); i++) {
		if (s[i] == ')') {
			if (s[i - 1] == '(')
				dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
			else {
				if (i - dp[i-1] > 0 && ((s[i - dp[i - 1] - 1]) == '(')) {
					dp[i] = dp[i - 1] + (i - dp[i-1] >= 2 ? dp[i - dp[i - 1] - 2]:0) + 2;
				}
			}
			res = max(res, dp[i]);
		}
	}
	return res;
}

四、总结

这道题我觉得栈实现是比较合理的,思路容易理解,而且运行时间快,但需要使用容器来实现;而动态规划就只需要一个数组就可以,但是转移方程需要思考一段时间。

你可能感兴趣的:(算法)