1.题目描述
2.选题原因
选择了一道动态规划的题目。但是感觉解这道题的方法不太像是动态规划的思想…一道匹配括号的题目,也是绞尽脑汁。
3.题目分析及算法
3.1分析
最容易想到的方法必然是用
stack
来解这道题目。思路如下:
3.2传统算法
遇到
(
将他放入栈,遇到)
则查看栈中是否有相匹配的括号(即栈是否为空)
- 栈为空,则说明该子串停止了。
- 栈不为空,则弹出一个括号,匹配到了一堆括号,字串长度
+ 2
。
3.3问题
很容易遇到问题,比如说遇到字串
()(()
,此时,正常的输出结果应该是2,但是我们的结果是4,运算的过程中,在第三个字符(
时,计数应该停止,但是栈继续计数,最后栈还剩下了元素。
如何避免这样的结果,有两种选择,第一种就是对两个字段分界的地方做记号,在循环之后返回标记点运算;第二种是提前判断。很明显,第二种方法更靠谱。
我们考虑,什么时候会出现一个字符串中断的情况:
第一种情况:出现(
第二种情况:出现)
出现)
的时候很容易判断,如果相匹配的括号,就肯定会终止,而如果还有括号就可能不会终止,如果只剩下栈里只剩下一个括号,就有可能会终止。
出现(
的时候就不好判断了,因为这回涉及到栈里的括号到最后能否匹配完的问题。
在这里,我们引入一种方法,用一个标记来标志字符串的开始位置,假设为start
。
只有当出现字符串终止的时候才有可能会调整start
的位置。
字符串结束的几个条件:
- 1、没有左括号与右括号匹配。
- 2、有左括号和右括号匹配,但仅剩最后一个左括号。此时就可以更新最大值。
- 3、有左括号和右括号匹配,且还有很多左括号。此时有可能多余的左括号会导致连接断开。
3.4算法
- 初始化
start = 0
,开始遍历字符串。- 遇到
(
,加入栈。- 遇到
)
,开始判断:
- 栈为空,说明字符串长度断开,
start = index + 1
- 栈不为空,弹出元素,再次判断:
- 栈中还有元素,更新
MAX = index - 栈顶元素坐标
- 栈中没有元素,更新
MAX = index - start + 1
4.运行结果
5.源代码
class Solution {
public:
int longestValidParentheses(string s) {
string::iterator iter; //迭代器
int result = 0; //记录最长的有效字符串长度
int start = 0; //记录有效字符串的开始位置
stack<int> st; //保存当前剩下的左括号的位置
int i = 0;
for (iter = s.begin(), i = 0; iter != s.end(); iter++, i++) {
if (*iter == '(') { //左括号则插入栈中
st.push(i);
} else { //否则判断
if (!st.empty()) { //不为空,说明还有有效字符串
st.pop();
if (!st.empty()) {
result = max(result, i - st.top());
} else {
result = max(result, i - start + 1);
}
} else { //为空,说明字符串已经结束了
start = i + 1;
}
}
}
return result;
}
};