给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。
返回所有可能的结果。答案可以按 任意顺序 返回。
示例 1:
输入:s = "()())()"
输出:["(())()","()()()"]
示例 2:
输入:s = "(a)())()"
输出:["(a())()","(a)()()"]
示例 3:
输入:s = ")("
输出:[""]
提示:
1 <= s.length <= 25s由小写英文字母以及括号'('和')'组成s中至多含20个括号
分析:BFS 的核心是按"删除括号的数量"一层一层搜索。
把原字符串作为第 0 层。如果它不合法,就枚举删除其中一个括号,得到第 1 层的所有字符串;如果第 1 层仍然没有合法结果,就继续删除一个括号,得到第 2 层。
由于 BFS 是按删除次数递增搜索的,所以第一次出现合法字符串时,这一层对应的删除次数一定是最少的。此时收集这一层所有合法字符串,直接结束搜索,不需要继续往下一层。
搜索过程中要使用集合进行去重,避免同一个字符串被重复加入队列。连续相同的括号也可以跳过重复删除的位置,进一步减少搜索量。
判断字符串是否合法时,从左到右扫描:遇到 ( 计数加一,遇到 ) 计数减一。如果中途计数小于 0,说明出现了无法匹配的右括号;最后计数为 0,则说明括号完全匹配。
因此整体思路就是:
原字符串 → 删除 1 个括号的所有情况 → 删除 2 个括号的所有情况 → ......
第一次找到合法字符串的那一层,就是最终答案。
cpp
class Solution {
public:
vector<string> removeInvalidParentheses(string s) {
vector<string>ans;
queue<string>q;q.push(s);
unordered_set<string>visited;visited.insert(s);
bool found=false;
while(!q.empty())
{
int size=q.size();
for(int k=0;k<size;k++)
{
string cur=q.front();q.pop();
if(isValid(cur))
ans.push_back(cur),found=true;
if(found)continue;
for(int i=0;i<cur.size();i++)
{
if(cur[i]!='('&&cur[i]!=')')continue;
if(i>0&&cur[i]==cur[i-1])continue;
string next=cur.substr(0,i)+cur.substr(i+1);
if(!visited.count(next))
visited.insert(next),q.push(next);
}
}
if(found)break;
}
return ans;
}
bool isValid(const string &s)
{
int cnt=0;
for (int i=0;s[i];++i)
{
char c=s[i];
if(c=='(')cnt++;
else if (c == ')')
{
cnt--;
if(cnt<0)return false;
}
}
return cnt==0;
}
};