leetcode32
2015-10-13 20:43
274 查看
leetcode32 ----------------longest valid parentheses
这道题目是找子串中最长匹配括号子串的长度,题目给的提示是动态规划,使用动态规划解题不是很熟,困扰了我很久。
只有硬着头皮用栈来做了。
这里给出三个解法,第一个是自己撸的,后两个是为了学习的。
我的思路是:
对于一长串括号来说,它存在两种情况:一种长串完全匹配,此时返回子串长度;一种是存在一些让串不匹配的字符,这样我们记录他们的索引,最后,夹在这些不匹配的字符的串就是匹配子串,我们索引相减即得到子串长度,再由此求出最长。
对于第二种情况,举个例子:
例如现在输入:”()()(()()()(((“
其中加黑部分表示不匹配的位置,则现在我们记录他们之间的差,求出最大值,再与第一个不匹配的索引比较(排除前缀匹配情况),最终的结果就是最长匹配串长度。
至于记录这些不匹配括号的位置就简单了:
维护一个栈分为几种情况:
1. 左括号,压栈
2. 右括号,此时如果栈顶为左括号,则弹栈;如果为右括号或者为空,则将右括号压栈(多余的右括号也可能成为让子串不匹配的字符)
代码如下:
网上看了一个非常好的思路,时间复杂度和空间复杂度都是O(n)
/article/1378341.html
看了思路后觉得真是厉害,所以尝试着写了一下,代码:
最后就是动态规划算法。说实话,DP一直是软肋,借这个题也是学习了一波。
动归就要有动归方程,仔细分析这道题,动归方程可以这样描述:
首先dp[i] 表示从s[i]往前推最长能匹配的子串,换句话说,就是到s[i]为止的最长匹配子串后缀。那么当对于下面几种情况进行分析:
1. s[i] ==’(’ s[i]为左括号,dp[i]=0这个很好理解。
2. s[i] ==’)’这就要分情况了
a) 如果s[i-1]是’(’说明已经完成了一次匹配,子串长度为2,但是还要加上dp[i-2]的大小,也就是当前匹配的这对括号前面的最长匹配长度,它们是相连的。
b) 如果s[i-1]是’)’这样不能匹配,则需要考虑s[i-1-dp[i-1]]的情况了,如果s[i-1-dp[i-1]]是一个左括号,则与当前右括号匹配,那么此时我们另dp[i]=dp[i-1]+2,这个2就是刚刚匹配的左右括号。最后还要把dp[i-2-dp[i-1]]值加起来,把相连的最大长度求出来。
代码:
这道题目是找子串中最长匹配括号子串的长度,题目给的提示是动态规划,使用动态规划解题不是很熟,困扰了我很久。
只有硬着头皮用栈来做了。
这里给出三个解法,第一个是自己撸的,后两个是为了学习的。
我的思路是:
对于一长串括号来说,它存在两种情况:一种长串完全匹配,此时返回子串长度;一种是存在一些让串不匹配的字符,这样我们记录他们的索引,最后,夹在这些不匹配的字符的串就是匹配子串,我们索引相减即得到子串长度,再由此求出最长。
对于第二种情况,举个例子:
例如现在输入:”()()(()()()(((“
其中加黑部分表示不匹配的位置,则现在我们记录他们之间的差,求出最大值,再与第一个不匹配的索引比较(排除前缀匹配情况),最终的结果就是最长匹配串长度。
至于记录这些不匹配括号的位置就简单了:
维护一个栈分为几种情况:
1. 左括号,压栈
2. 右括号,此时如果栈顶为左括号,则弹栈;如果为右括号或者为空,则将右括号压栈(多余的右括号也可能成为让子串不匹配的字符)
代码如下:
class Solution { public: int longestValidParentheses(string s) { //维护两个栈,一个是括号,一个是索引 stack<char> parenthese; stack<int>index; int len = s.size(); int i; for (i = 0; i < len; i++) { if (s[i] == '(')//左括号进栈 { index.push(i); parenthese.push(s[i]); } else { if (!parenthese.empty() && parenthese.top() == '(')//必须同时满足这两个条件,因为右括号也可以作为隔断匹配子串的字符 { index.pop(); parenthese.pop(); } else//此时将不匹配的不论是左括号还是右括号,都进栈 { index.push(i); parenthese.push(s[i]); } } } vector<int>myCount; if (index.empty())//没有隔断的字符元素 { return len; } while (!index.empty())//这里用容器来处理较为方便 { myCount.push_back(index.top()); index.pop(); } int maxCount = myCount[myCount.size() - 1]; if (myCount.size() > 1) { for (i = 0; i < myCount.size() - 1; i++) { maxCount = max(maxCount, myCount[i] - myCount[i + 1] - 1); } }//循环求两个不匹配元素中间隔的匹配子串长度,并求最大值 maxCount = max(maxCount, len - myCount[0] - 1);//排除前缀是匹配子串的情况 return maxCount; } };
网上看了一个非常好的思路,时间复杂度和空间复杂度都是O(n)
/article/1378341.html
看了思路后觉得真是厉害,所以尝试着写了一下,代码:
class Solution { public: int longestValidParentheses(string s) { int i; stack<int>index; int maxCount = 0; int startIndex = 0; for (i = 0; i < s.size(); i++) { if (s[i] == '(') { index.push(i);//左括号进栈 } else if (s[i] == ')') { if (!index.empty())//非空 { index.pop();//匹配一组弹栈 if (index.empty())//如果空了,说明当前匹配完成 { maxCount = max(maxCount, i - startIndex + 1); } else//否则,由当前索引减去栈顶元素索引,表示弹出的元素与当前匹配右括号之间字符长度 { maxCount = max(maxCount, i - index.top()); } } else//如果为空,说明上一组最长子串已经匹配完,startIndex滑动到下一个字符 { startIndex = i + 1; } } } return maxCount; } };
最后就是动态规划算法。说实话,DP一直是软肋,借这个题也是学习了一波。
动归就要有动归方程,仔细分析这道题,动归方程可以这样描述:
首先dp[i] 表示从s[i]往前推最长能匹配的子串,换句话说,就是到s[i]为止的最长匹配子串后缀。那么当对于下面几种情况进行分析:
1. s[i] ==’(’ s[i]为左括号,dp[i]=0这个很好理解。
2. s[i] ==’)’这就要分情况了
a) 如果s[i-1]是’(’说明已经完成了一次匹配,子串长度为2,但是还要加上dp[i-2]的大小,也就是当前匹配的这对括号前面的最长匹配长度,它们是相连的。
b) 如果s[i-1]是’)’这样不能匹配,则需要考虑s[i-1-dp[i-1]]的情况了,如果s[i-1-dp[i-1]]是一个左括号,则与当前右括号匹配,那么此时我们另dp[i]=dp[i-1]+2,这个2就是刚刚匹配的左右括号。最后还要把dp[i-2-dp[i-1]]值加起来,把相连的最大长度求出来。
代码:
class Solution { public: int longestValidParentheses(string s) {//dp int len = s.size(); vector<int>dp(len); int maxCount = 0; for (int i = 0; i < len; i++) { if (s[i] == '(') dp[i] = 0; else { if (i - 1 >= 0)//考虑输入"()" { if (s[i - 1] == '(') { dp[i] = 2; if (i - 2 >= 0) { dp[i] += dp[i - 2]; } } else { if (i - dp[i - 1] - 1 >= 0 && s[i - dp[i - 1] - 1] == '(') { dp[i] = dp[i - 1] + 2; if (i - dp[i - 1] - 2 >= 0) dp[i] += dp[i - dp[i - 1] - 2]; } } } } maxCount = max(maxCount, dp[i]); } return maxCount; } };
相关文章推荐
- 3.Maximum Depth of Binary Tree
- hadoop2.6+ zookeeper3.4.6搭建
- java 策略模式
- wifi调试android 设备的方法
- openfire源码分析---1
- 二叉树前序遍历
- 仿写聊天气泡界面
- nyoj 南阳理工63小猴子下落
- javac和java -cp选项情景总结
- 数据结构 线性表
- 指针
- 堆排序
- PHP学习笔记(10)—— 浮点数与运算优先级
- SGI STL中的construct
- 神经网络&深度学习
- eclipse相关问题一:无法import项目,显示 select at list one project
- 杭电acm--1046
- 【曾经】图片快速分割
- WaitForSingleObject的用法
- 深入浅出Android App耗电量统计