leetcode 20. 有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
分析:此题借助栈,逐一分析即可。
class Solution {
public:
bool isValid(string s) {
stack<char> mystack;
unordered_map<char, char> pairs = {
{'}', '{'},
{']', '['},
{')', '('}
};
if (s.size() % 2 == 1) {
return false;
}
for (char ch : s) {
if (pairs.count(ch)) {
if (mystack.empty() || mystack.top() != pairs[ch]){
return false;
}
mystack.pop();
} else {
mystack.push(ch);
}
}
return mystack.empty();
}
};
leetcode 22. 括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1
输出:["()"]
分析:此题要输出正常的括号,所以输出的字符串中截止到任意一位置,左括号数一定是大于等于右括号数的。
class Solution {
public:
void gen(vector<string> & result, string str, int left, int right) {
if (left == 0 && right == 0) {
result.push_back(str);
return;
}
if (left > 0) {
gen(result, str + "(", left - 1, right);
}
if (left < right && right > 0) {
gen(result, str + ")", left, right - 1);
}
}
vector<string> generateParenthesis(int n) {
vector<string> result;
gen(result, "", n, n);
return result;
}
};
32. 最长有效括号
给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 “()”
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 “()()”
示例 3:
输入:s = ""
输出:0
分析:此题需要借助动态规划,dp[n] 表示截止当前n位置最长有效括号子串长度
class Solution {
public:
int longestValidParentheses(string s) {
int maxlen = 0;
int n = s.size();
if (n == 0) {
return maxlen;
}
vector<int> dp(n, 0);
for (int i = 1; i < n; ++i) {
if (s[i] == ')') {
if (s[i - 1] == '(') {
dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
}
else if (i - dp[i-1] - 1 >= 0 && s[i - dp[i-1] -1] == '(') {
dp[i] = 2 + dp[i-1] + ((i - dp[i-1]) >= 2? dp[i - dp[i - 1] -2] : 0);
}
}
if (dp[i] > maxlen) {
maxlen = dp[i] ;
}
}
return maxlen;
}
};
301.删除无效的括号
删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果。
说明: 输入可能包含了除 ( 和 ) 以外的字符。
示例 1:
输入: "()())()"
输出: ["()()()", "(())()"]
示例 2:
输入: "(a)())()"
输出: ["(a)()()", "(a())()"]
示例 3:
输入: ")("
输出: [""]
分析:
方法一:采用回溯的思想,每个位置分别考虑删除以及保留的情况。
方法二:采用BFS,一层层的找。
class Solution {
private:
int length ;
vector<string> result;
string str;
public:
vector<string> removeInvalidParentheses(string s) {
int leftRemove = 0;
int rigthRemove = 0;
length = s.size();
str = s;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '(') {
leftRemove++;
} else {
if(s[i] == ')') {
if (leftRemove > 0) {
leftRemove--;
} else {
rigthRemove++;
}
}
}
}
dfs(0, 0, 0, leftRemove, rigthRemove, "");
return result;
}
void dfs(int index, int leftCount, int rightCount, int leftRemove, int rightRemove, string path) {
if (index == length) {
if (leftRemove == 0 && rightRemove ==0) {
vector<string>::iterator it;
it = find(result.begin(), result.end(), path);
if( it == result.end() ) // finded
{
result.push_back(path);
}
}
return;
}
可能的操作 1:删除当前遍历到的字符
if(str[index] == '(' && leftRemove > 0) {
//leftRemove > 0,并且当前遇到的是左括号,可以尝试删除当前遇到的左括号
dfs(index + 1, leftCount, rightCount, leftRemove - 1, rightRemove, path);
}
if (str[index] == ')' && rightRemove > 0) {
//ightRemove > 0,并且当前遇到的是右括号,因此可以尝试删除当前遇到的右括号
dfs(index + 1, leftCount, rightCount, leftRemove, rightRemove - 1, path);
}
可能的操作 2:保留当前遍历到的字符
path.push_back(str[index]);
if (str[index] != '(' && str[index] != ')') {
dfs(index + 1, leftCount, rightCount, leftRemove, rightRemove, path);
} else if (str[index] == '(') {
// 考虑左括号
dfs(index + 1, leftCount + 1, rightCount, leftRemove, rightRemove, path);
} else if (rightCount < leftCount) {
// 考虑右括号
dfs(index + 1, leftCount, rightCount + 1, leftRemove, rightRemove, path);
}
path.erase(path.size() - 1);
}
};
class Solution {
public:
bool isValid(string s) {
int leftCount = 0;
for(char ch : s) {
if(ch == '(') {
leftCount++;
} else if (ch == ')') {
leftCount--;
}
if(leftCount < 0) {
return false;
}
}
return leftCount == 0;
}
vector<string> removeInvalidParentheses(string s) {
vector<string> result;
if(s.size() == 0) {
return {""};
}
if(isValid(s)) {
return {s};
}
queue<string> q;
unordered_set<string> lookup; // 是否被访问过
q.push(s);
lookup.insert(s);
while(!q.empty()) {
int n = q.size();
for (int i = 0; i < n; ++i) {
string str = q.front();
q.pop();
for (int j = 0; j < str.size(); ++j) {
if (str[j] != '(' && str[j] != ')') {
continue;
}
string temp = str;
string str1 = temp.erase(j, 1);
if(isValid(str1) && lookup.count(str1) == 0) {
vector<string>::iterator it;
it = find(result.begin(), result.end(), str1);
if(it == result.end()) {
result.push_back(str1);
}
} else {
if(lookup.count(str1) == 0) {
q.push(str1);
}
}
lookup.insert(str1);
}
}
if(result.size() != 0) {
return result;
}
}
return result;
}
};