20. 有效的括号(栈)
leetcode 20
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 注意空字符串可被认为是有效字符串。
思路: 因为有效括号字符串必须要相互匹配,从左向右遍历时不能存在当前位置之前右括号比左括号多的情况,栈可以辅助我们完成这一判断。
class Solution {
public:
bool isValid(string s) {
// 定义不同括号的配对关系
unordered_map<char, char> map;
map['('] = ')';
map['['] = ']';
map['{'] = '}';
// 声明一个栈,用来储存左括号,并与新来的括号做比对
stack<char> st;
int i = 0;
while(i < s.size()) {
if(s[i] == '(' || s[i] == '[' || s[i] == '{') st.push(s[i]); // 左括号入栈
else {
if(!st.empty() && map[st.top()] == s[i]) st.pop(); // 右括号与栈顶左括号匹配,栈顶左括号出栈
else return false; // 栈空时出现右括号 or 右括号与栈顶左括号不匹配,返回false
}
i++;
}
// 遍历完所有括号,如果栈空则是有效字符串返回true,否则返回false
return st.empty() ? true : false;
}
};
22. 括号生成(dfs)
leetcode 22
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的括号组合。
思路: 因为题目要求生成所有可能的括号组合,所以想到可以使用dfs暴力搜索所有的可能性。同时需要注意为了保证生成的是有效括号,不能让当前字符串中的右括号数大于左括号数。
class Solution {
public:
vector<string> ans;
void dfs(string& res, int l, int r) {
// 当左、右括号全部用完时,即生成了一个有效括号组合,加入ans,返回
if(l == 0 && r == 0) {
ans.push_back(res);
return;
}
// 如果还有左括号剩余,则添加一个左括号
if (l > 0) {
res += '(';
dfs(res, l - 1, r);
res.erase(res.end() - 1); // 回退
}
// 如果剩余的右括号数大于剩余的左括号数,则添加一个右括号
if (r > l) {
res += ')';
dfs(res, l, r - 1);
res.erase(res.end() - 1); // 回退
}
}
vector<string> generateParenthesis(int n) {
// 声明一个存储可能组合的字符串
string res;
// 因为所有可能性都要被找出,所以dfs为void型函数,需要迭代各种可能性
dfs(res, n, n);
return ans;
}
};
32. 最长有效括号(动态规划)
leetcode 32
给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
思路: 因为题目要求最长的包含有效括号的子串的长度,是一个最值问题,往往可以使用动态规划来解决。注意这里dp数组的含义:以第i个元素结尾的子串中最长的有效括号的长度为dp[i],而不是前i个元素的最长的有效括号的长度。
class Solution {
public:
int longestValidParentheses(string s) {
int n = s.size();
if(n < 2) return 0;
// 声明dp数组,以第i个元素结尾的子串中最长的有效括号的长度为dp[i]
int dp[n];
memset(dp, 0, sizeof(dp));
// 循环更新dp数组
int maxx = 0;
for(int i = 1; i < n; i++) {
// 如果当前为左括号'('则以其结尾的子串必然不包含有效括号,dp[i]依旧为0
if(s[i] == ')') {
// 在当前为')'的情况下,如果前一个为'(',用前前一个的最长包含有效括号的子串长度加2即可
if(s[i-1] == '(')
dp[i] = (i >= 2 ? dp[i-2] : 0) + 2;
// 如果前一个为')',例如:"()(()())",并且s[i - dp[i-1] - 1]也为'('时,dp[i]才不为0,此时还需要考虑dp[i - dp[i-1] - 2]的值
else if(i - dp[i-1] - 1 >= 0 && s[i - dp[i-1] - 1] == '(')
dp[i] = (i - dp[i-1] - 2 >= 0 ? dp[i - dp[i-1] - 2] : 0) + dp[i-1] + 2;
maxx = max(maxx, dp[i]); // 更新最长包含有效括号的子串长度
}
}
return maxx;
}
};