0%

leetcode 32 最长的有效括号

Leetcode 32 最长的有效括号

开胃菜 Leetcode 20 有效括号

给定一个字符串,判断括号等符号个数能否匹配正确
很明显,需要使用堆栈,流程: 1. 遇到左侧符号时,将其推入到栈中 2. 遇到右侧符号时,判断栈是否为空 3. 若栈为空,直接 return false ,因为这时候需要一个左括号弹出栈,而我们是空栈,所以不匹配 4. 若栈不为空,判断栈顶元素是否与当前符号相匹配,若匹配,则弹出,若不匹配,则 return false 5. 返回第一步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
bool isValid(string s) {
stack<char> ss;
for(int i=0;i<s.length();i++){
if(s[i]=='('||s[i]=='{'||s[i]=='[')
ss.push(s[i]);
else{
if(ss.empty()) return false;
if(s[i]==')'&&ss.top()=='(')
{
ss.pop();
}else if(s[i]=='}'&&ss.top()=='{')
{
ss.pop();
}else if(s[i]==']'&&ss.top()=='['){
ss.pop();
}else
return false;
}
}
if(ss.empty()) return true;
else return false;
}
};

算法复杂度 O(n)
注意: 记得遇到右侧符号的时候,要检查栈是否为空,否则后面会访问空栈

Leetcode 32 最长的有效括号

Hard

brute force 爆破

首先想到的是遍历所有的子字符串,长度从1-n,长度为 1 的有 n 个,长度为 2 的有 n-1 个,....,长度为 n 的只有 1 个,所以子字符串的个数总数为 n*n 个,并且我们检查一个子字符串是否为有效的匹配,复杂度是 n,因此最后的复杂度是 n 的立方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public:
bool isvalid(string s){
stack<char> ss;
for(int i=0;i<s.length();i++){
if(s[i]=='('){
ss.push(s[i]);
}else if(!ss.empty()){
ss.pop();
}else{
return false;
}
}
return ss.empty();
}


int longestValidParentheses(string s) {
int cnt=0;
for(int i=0;i<s.length();i++){
for(int j=i+2;j<=s.length();j+=2){
if(isvalid(s.substr(i,j-i))){
cnt=max(j-i,cnt);
}
}
}
return cnt;
}
};

提交之后: 超时

利用堆栈

因为本题目中的符号只有 '(' ')',所以我们考虑向堆栈中推入字符串的 index。利用堆栈保存下上个有效匹配括号的索引。

  1. 逐个遍历字符串
  2. 假如字符串是 '(' ,将其 index 压入栈中
  3. 假如是 ')' ,出栈
  4. 判断此时栈是否为空,若为空,则表示前面的符号都已经匹配,当前符号并不会匹配前面,是新的开始,所以将当前 index 压入栈中
  5. 若栈不为空,则表示连续匹配,此时更新 maxlength=max(maxlength,i-ss.top()), ss.top()表示的是本次最长匹配的开头位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
int longestValidParentheses(string s) {
int maxlength=0;
stack<int> ss;
ss.push(-1);
for(int i=0;i<ss.length();i++){
if(s[i]=='('){
ss.push(i);
}else{
ss.pop();
if(ss.empty()){
ss.push(i);
}else{
maxlength=max(maxlength,i-ss.top());
}
}
}
}
};