Longest Valid Parentheses题解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jining11/article/details/82868721

题目要求

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 "()()"

思路一:抱着试试看的心态打了分治

class Solution {
public:
	bool is_valid(string s) {
		//判断是否合法 
		stack <char> ST;
		for (auto c: s) {
			if (!ST.empty()&&ST.top() == '(' && c == ')') {
				ST.pop();
			}
			else {
				ST.push(c); 
			}
		}
		return ST.empty();
	}
	
	
    int longestValidParentheses(string s) {
    	cout << s << endl;
    	if (s.size() < 2) {
    		return 0;
		}
    	int start = 0, end = s.size()-1;
    	//首先确保以'('开头以')'结束 
    	for (;s[start] == ')' && start <= end; start++);
    	for (;s[end] == '(' && end >= start; end--);
    	if (end == start) {
    		return 0;
		}
		s = s.substr(start, end-start+1);
    	if (is_valid(s)) {
    		return s.size();
    	}
    	else {
    		int m1 = longestValidParentheses(s.substr(1));
    		int m2 = longestValidParentheses(s.substr(0, s.size()-1));
    		return max(m1,m2);
    	}
    }
};

运行结果如下:

这是因为分治时会重复讨论某些情况,比如说,‘(()’第一次分治后分别处理'(('和'()',‘((’分治后获得'(','()'分治后会重复'('这一情况。

思路二:抱着这样应该能过的吧的心态打了迭代

充分利用以下特征遍历所有情况:

  • 合法序列的长度必定为2
  • 合法序列必定以‘(’和‘)’作为开头和结尾
  • 其长度必须大于当前查找到的最大长度
class Solution {
public:
	bool is_valid(string s) {
		//判断是否合法 
		stack <char> ST;
		for (auto c: s) {
			if (!ST.empty()&&ST.top() == '(' && c == ')') {
				ST.pop();
			}
			else {
				ST.push(c); 
			}
		}
		return ST.empty();
	}
	
	
    int longestValidParentheses(string s) {
    	int start = 0, end = s.size()-1;
    	//首先确保以'('开头以')'结束 
    	for (;s[start] == ')' && start <= end; start++);
    	for (;s[end] == '(' && end >= start; end--);
    	if (end == start) {
    		return 0;
		}
		int mmax = 0;
		int final = 0;
		while (start+mmax <= end+1) {
			final = start+max(mmax,2)-1;
			while(final <= end) {
				if (s[final] == ')' && is_valid(s.substr(start, final-start+1))) {
					mmax = final-start+1;
				}
				final += 2;
			}
			start++;
			for (;s[start] == ')'; start++);
		}
		return mmax;
    }
};

反正这个迭代法我是优化不下去了。。。然鹅离通过测验还是差了几步之遥。

思路三 抱着不会今天都过不了了吧的心态打了动态规划

首先,对于一个长为len的字符串s,维护一个长为len的状态数组dp,其中,dp[i]的含义为s中从i开始且包含i的最长合法序列。

  • 初始状态:dp = [0...0]
  • 状态转移方程:
    • 如果s[i-1]为'('且s[i+dp[i]]为')',那么dp[i-1] = dp[i]+2.如果j = i-1+dp[i-1]没有越界,那么dp[i-1]还要加上dp[j]
  • 举个例子:'(())'
    • s[3] = '(',s[2] = '(',因此dp[2]、dp[3]依然为0;
    • s[1] = '(', s[2+dp[2]]=')',dp[1] = dp[2]+2 = 2, 由于1+dp[1] = 3仍然位于s内部,因此dp[1] = dp[1]+dp[3] = 2;
    • s[0] = '(', s[1+dp[1]]=')',dp[0] = dp[1]+2 = 4, 由于0+dp[0] = 4超出s,因此dp[0] = 4;
class Solution {
public:
    int longestValidParentheses(string s) {
    	int start = 0, end = s.size()-1;
    	//首先确保以'('开头以')'结束 
    	for (;s[start] == ')' && start <= end; start++);
    	for (;s[end] == '(' && end >= start; end--);
    	int* dp = new int[s.size()+1]();//多出一位不用判断了
    	int mmax = 0;
    	for (int i = end-1; i >= start; i--) {
    		if (s[i] == '(' && s[i+1+dp[i+1]] == ')') {
    			dp[i] = dp[i+1]+2+dp[i+2+dp[i+1]];
    			mmax = mmax > dp[i] ? mmax : dp[i];
    		}
    	}
    	return mmax;
    }
};

思路四:抱着原来竟然真的可以这样做的心态打了栈解法

class Solution {
public:

    int longestValidParentheses(string s) {
    	int start = 0, mmax = 0;
    	stack <int> ST;
    	//这次栈里面的元素是字符串里面‘(’的索引
		for (int i = 0; i < s.size(); i++) {
			if (s[i] == '(') {
				ST.push(i);
			}
			else {
				if (ST.empty()) {
					start = i+1;
				}
				else {
					ST.pop();
					mmax = ST.empty() ? max(mmax, i-start+1) : max(mmax, i-ST.top());
				}
			}
		}
		return mmax;
    }    
};

 

累了累了

猜你喜欢

转载自blog.csdn.net/jining11/article/details/82868721