301. Remove Invalid Parentheses
Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.
Note: The input string may contain letters other than the parentheses (
and )
.
Example 1:
Input: "()())()"
Output: ["()()()", "(())()"]
Example 2:
Input: "(a)())()"
Output: ["(a)()()", "(a())()"]
Example 3:
Input: ")("
Output: [""]
// BFS
bool isValid(const string& str) {
int cnt = 0;
for (char ch : str) {
if (ch == '(') ++cnt;
else if (ch == ')' && --cnt < 0) return false;
}
return cnt == 0;
}
vector<string> removeInvalidParentheses(string s) {
vector<string> res;
unordered_set<string> visited({s});
queue<string> q({s});
bool found = false;
while (!q.empty()) {
string t = q.front(); q.pop();
if (isValid(t)) {
res.push_back(t);
found = true;
}
if (found) continue;
// Remove one char from the t string
for (int i = 0; i < t.length(); ++i) {
if (t[i] != '(' && t[i] != ')') continue;
string new_str = t.substr(0, i) + t.substr(i + 1);
if (!visited.count(new_str)) {
q.push(new_str);
visited.insert(new_str);
}
}
}
return res;
}
// Recursion
bool isValid(const string& s) {
int cnt = 0;
for (int i = 0; i < s.length(); ++i) {
if (s[i] == '(') ++cnt;
else if (s[i] == ')' && --cnt < 0) return false;
}
return cnt == 0;
}
void helper(string s, int start, int cnt1, int cnt2, vector<string>& res) {
if (cnt1 == 0 && cnt2 == 0) {
if (isValid(s)) res.push_back(s);
return;
}
for (int i = start; i < s.length(); ++i) {
if (i != start && s[i] == s[i - 1]) continue;
if (cnt1 > 0 && s[i] == '(') {
helper(s.substr(0, i) + s.substr(i + 1), i, cnt1 - 1, cnt2, res);
}
if (cnt2 > 0 && s[i] == ')') {
helper(s.substr(0, i) + s.substr(i + 1), i, cnt1, cnt2 - 1, res);
}
}
}
vector<string> removeInvalidParentheses(string s) {
vector<string> res;
int cnt1 = 0, cnt2 = 0; // cnt1: surplus number of (, cnt2: surplus number of )
// Calculate cnt1 and cnt2
for (char ch : s) {
cnt1 += (ch == '(');
if (cnt1 == 0) cnt2 += (ch == ')');
else cnt1 -= (ch == ')');
}
helper(s, 0, cnt1, cnt2, res);
return res;
}
// Optimized Recursion
void helper(string s, int start, int last_del, const string& p, vector<string>& res) {
int cnt = 0;
for (int i = start; i < s.length(); ++i) {
if (s[i] == p[0]) ++cnt;
else if (s[i] == p[1]) --cnt;
if (cnt >= 0) continue;
// Delete extra p[1]
for (int j = last_del; j <= i; ++j) {
if (s[j] == p[1] && (j == last_del || (s[j] != s[j - 1]))) {
helper(s.substr(0, j) + s.substr(j + 1), i, j, p, res);
}
}
return; // if the program runs to here, no need to reverse to delete extra p[0]
}
// Delete extra p[0]
string rev = string(s.rbegin(), s.rend());
if (p[0] == '(') helper(rev, 0, 0, ")(", res);
else res.push_back(rev);
}
vector<string> removeInvalidParentheses(string s) {
vector<string> res;
helper(s, 0, 0, "()", res);
return res;
}
Last updated
Was this helpful?