1.有效的括号
leetcode 20
考虑到有效匹配的问题,可以采用栈的方法,每次匹配上一个栈顶的字符,不符合就返回,将左括号放入栈中,用右括号去匹配,思路如下:
class Solution {
public:
char returnWord(char c){
char res = '0';
switch(c){
case ')':
res = '(';
break;
case '}':
res = '{';
break;
case ']':
res = '[';
break;
default:
break;
}
return res;
}
bool isValid(string s) {
stack<char> st; //建立一个栈
if(s.size()==0)
return true;
if(s.size()&1) //考虑不符合的输入情况
return false;
int n = s.size();
for(int i=0; i<n; i++){
if(s[i]=='(' || s[i]=='[' || s[i]=='{')
st.push(s[i]);
else{
if(st.empty() || returnWord(s[i])!=st.top()) // 调用函数去匹配,也可以采用哈希表去匹配,没有匹配成功或者没有带匹配的元素,即返回失败
return false;
else
st.pop();
}
}
return st.empty();
}
};
2.括号生成
leetcode 22
需要返回所有满足的有效括号集合,可以采用深度优先遍历的解法,不符合的结果进行剪枝,解法如下:
class Solution {
public:
vector<string> res; //全局变量用于返回
vector<string> generateParenthesis(int n) {
string tmp;
dfs(tmp, n, 0, 0);
return res;
}
void dfs(string tmp, int n, int left, int right){ //深度优先遍历
if(left>n || right>left) //左括号超过目标数量,右括号比左括号多
return;
if(tmp.size()==2*n){ //经过筛选后所得即为结果
res.push_back(tmp);
return;
}
dfs(tmp+"(", n, left+1, right);
dfs(tmp+")", n, left, right+1);
}
};
3.最长有效括号
leetcode 32
解法一:用栈解决,利用指针移动,选取匹配元素开始的位置,每次将左括号的位置入栈,然后匹配到右括号时,计算此时的最大长度,如果此时栈里面没有元素时,直接计算当前长度,栈里面还有元素时需要,考虑可能是中间多个元素匹配后得长度,需要计算此时位置与栈顶元素的长度差,如果来了一个右括号但没有匹配成功就要更新开始元素位置,代码如下:
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> st;
int ans = 0;
int start = 0;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == '(')
st.push(i);
else
{
if (!st.empty())
{
st.pop();
if (st.empty())
ans = max(ans, i - start + 1);
else
ans = max(ans, i - st.top());
}
else
start = i + 1;
}
}
return ans;
}
};
解法二:动态规划
定义一个数组DP[i],状态i为以i结尾的元素的最长有效括号数;
第一种情况:
当第i个元素为左括号时,以它结尾的有效括号长度为0,
第二种情况:
当第i个元素为右括号时,开始与前面元素匹配最长有效括号
(1)如果前一个元素为左括号,直接匹配成功,且最长有效括号长度要加上i-2元素位置的有效括号长度
(2)如果前一个元素为右括号,则判断i-1位置元素是否是有效的,如果有效则判断i-dp[i-1]-1位置的元素是否是左括号,是的话则匹配成功,且需进一步判断是否因为此次匹配成功,前面i-dp[i-1]-2位置的有效括号是否能加入此次匹配的最长长度中
注意:每次索引数组下标需要判断下是否有效
代码如下:
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.size();
vector<int> dp(n);
int res = 0;
for(int i=1; i<n; i++){
if(s[i]==')'){
if(s[i-1]=='('){
dp[i] = i>=2 ? (dp[i-2]+2) : 2;
}
else if(dp[i-1]>0){
//dp[i] = dp[i-1];
if(i-dp[i-1]-1>=0 && s[i-dp[i-1]-1]=='('){
dp[i] = 2 + dp[i-1];
if(i-dp[i-1]-2>=0){
dp[i] = 2 + dp[i-1] + dp[i-dp[i-1]-2];
}
}
}
}
res = max(res, dp[i]);
}
return res;
}
};
4.有效的括号字符串
leetcode678
栈解决:
定义两个栈,一个用于存储左括号,一个用于存储星号,第一遍遍历,用两个栈来比较看是否能够存在匹配的有效字符串,并将下标元素其存入栈中
第二遍查看星号的下标是否位于左括号的右侧,符合一对则pop出来,最后如果左括号栈还有没有匹配的元素则返回false
代码如下:
class Solution {
public:
bool checkValidString(string s) {
stack<int> left; //存储左括号
stack<int> middle; //存储星号
int n = s.size();
for(int i=0; i<n; i++){
if(s[i]=='(')
left.push(i);
else if(s[i]==')'){
if(!left.empty()){
left.pop();
}
else if(!middle.empty()){
middle.pop();
}
else{
return false;
}
}
else{
middle.push(i);
}
}
while(!middle.empty()){
if(!left.empty()){
if(left.top()>middle.top()){
return false;
}
left.pop();
}
middle.pop();
}
return left.empty();
}
};