力扣301题,删除无效的括号
题目描述
给你一个由若干括号和字母组成的字符串 s
,删除最小数量的无效括号,使得输入的字符串有效。
返回所有可能的结果。答案可以按 任意顺序 返回。
输入输出样例
输入:s = "()())()"
输出:["(())()","()()()"]
输入:s = "(a)())()"
输出:["(a())()","(a)()()"]
输入:s = ")("
输出:[""]
解法一:使用DFS+剪枝
class Solution
{
public:
//删除最小数量的括号,使得输入的字符串有效
vector<string>removeInvalidParenthese(string s)
{
//定义最小需要去除的左括号的数目与右括号的数目
int lRemove=0;
int rRemove=0;
for(char c:s)
{
if(c=='(')
{
lRemove++;
}
else if(c==')')
{
//确保在左右括号有效的前提下更新最小需要去除的左右括号的数目
if(lRemove==0)
{
rRemove++;
}
else{
lRemove--;
}
}
}
vector<string>res;
//去除字符串中无效的括号
removeParentheses(s,res,0,lRemove,rRemove);
return res;
}
void removeParentheses(string str,vector<string>&res,int start,int lRemove,int rRemove)
{
//需要更新的最小括号数目均为0时,那么则判断该字符串是否是有效的括号
if(lRemove==0&&rRemove==0)
{
if(isValid(str))
{
res.push_back(str);
}
return;
}
for(int i=start;i<str.size();i++)
{
//跳过之前相同的元素值,相当于剪枝
if(i!=start&&str[i]==str[i-1])
{
continue;
}
//如果剩余的字符无法满足去掉的数量需求,直接返回
if(lRemove+rRemove>str.size()-i)
{
return;
}
//尝试去掉一个左括号
if(lRemove>0&&str[i]=='(')
{
string tempStr=str.substr(0,i)+str.substr(i+1);
removeParentheses(tempStr,res,i,lRemove-1,rRemove);
}
//尝试去掉一个右括号
if(rRemove>0&&str[i]==')')
{
string tempStr=str.substr(0,i)+str.substr(i+1);
removeParentheses(tempStr,res,i,lRemove,rRemove-1);
}
}
}
//判断是否为有效的括号
bool isValid(string s)
{
stack<char>stk;
for(auto i:s)
{
if(!stk.empty())
{
char temp=stk.top();
if(temp=='('&&i==')')
{
stk.pop();
continue;
}
}
if(i=='(')
{
stk.push(i);
}
}
return stk.empty();
}
};
解法二:BFS
//使用广度优先
class bfsSolution
{
public:
//判断是否为有效的括号
bool isValid(string s)
{
stack<char>stk;
for(auto i:s)
{
if(!stk.empty())
{
char temp=stk.top();
if(temp=='('&&i==')')
{
stk.pop();
continue;
}
}
if(i=='('||i==')')
{
stk.push(i);
}
}
return stk.empty();
}
//使用广度优先搜索的方法实现去除多余的括号
vector<string>removeInvalidParenthese(string str)
{
vector<string>res;
unordered_set<string>currStr;
//往hash表中插入原始字符串
currStr.insert(str);
//进行层序遍历
while(true)
{
//将括号字符串先按照从1到字符串长度递减操作
//直至出现能满足有效字符串的值
//只要大于一便可以弄进结果中
for(auto &str:currStr)
{
if(isValid(str))
{
res.push_back(str);
}
}
if(res.size()>0)
{
return res;
}
//保存切分的数组
unordered_set<string>nextStr;
for(auto &str:currStr)
{
for(int i=0;i<str.size();i++)
{
//跳过前一个值和后一个值相同的情况,因为此时无论删除那个都不影响
if(i>0&&str[i]==str[i-1])
{
continue;
}
//切分字符串
if(str[i]=='('||str[i]==')')
{
string tempStr=str.substr(0,i)+str.substr(i+1);
nextStr.insert(tempStr);
}
}
}
currStr=nextStr;
}
}
};