版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Viscu/article/details/82535118
删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果。
说明: 输入可能包含了除 ( 和 ) 以外的字符。
示例 1:
输入: “()())()”
输出: [“()()()”, “(())()”]
示例 2:
输入: “(a)())()”
输出: [“(a)()()”, “(a())()”]
示例 3:
输入: “)(”
输出: [“”]
思路:做过括号匹配都知道:用一个栈来模拟匹配过程,'('入栈,')'出栈,若栈为空说明该串是符合题意的。
现在我们需要做的就是对括号进行删除,我们遍历从前往后遍历可以删除不符合的')'括号,从后往前遍历可以删除
不符合的'('括号,我们利用bfs,不断对队列的字符串进行checkLeft和checkRight,若遇到ture,说明
当前的字符串已经是删除最少无效的括号的最优解了,接着就对队列中的其他字符串进行check即可,符合加入List中。
public class Solution {
public List<String> removeInvalidParentheses(String s) {
queue.offer(s);
vis.add(s);
boolean flag=false;
List<String> ans=new ArrayList<String>();
while (!queue.isEmpty()){
String cur=queue.poll();
if(flag){
check(cur,ans);
}else{
flag=checkLeft(cur,ans)||checkRight(cur,ans);
}
}
if(ans.size()==0){
ans.add("");
}
return new ArrayList<String>(ans);
}
Set<String> vis=new HashSet<String>();
Queue<String> queue=new LinkedList<String>();
public void check(String s,List<String> ans){ //查看是否正确
Stack<Character> st=new Stack<Character>();
for(char c:s.toCharArray()){
if(c=='('){
st.push(c);
}
if(c==')'){
if(st.isEmpty()){
return;
}
st.pop();
}
}
if(st.isEmpty()){
ans.add(s);
}
}
public boolean checkLeft(String s,List<String> ans){ //检查左边
//delete right
Stack<Character> st=new Stack<Character>();
for(int i=0;i<s.length();++i){
if(s.charAt(i)=='('){
st.push(s.charAt(i));
}else if(s.charAt(i)==')'){
if(st.isEmpty()){
for(int j=i;j>=0;--j){ //删除不符合的')' 多种情况
if(s.charAt(j)==')'){
String s1=s.substring(0,j)+s.substring(j+1);
if(!vis.contains(s1)){
vis.add(s1);
queue.offer(s1);
}
}
}
return false;
}else{
st.pop();
}
}
}
if(st.isEmpty()){
ans.add(s);
return true;
}
return false;
}
public boolean checkRight(String s,List<String> ans){ //检查右边
//delete right
Stack<Character> st=new Stack<Character>();
st.clear();
for(int i=s.length()-1;i>=0;--i){
if(s.charAt(i)==')'){
st.push(s.charAt(i));
}else if(s.charAt(i)=='('){
if(st.isEmpty()){
for(int j=i;j<s.length();++j){
if(s.charAt(j)=='('){ //删除不符合的'(' 多种情况
String s1=s.substring(0,j)+s.substring(j+1);
if(!vis.contains(s1)){
vis.add(s1);
queue.add(s1);
}
}
}
return false;
}else{
st.pop();
}
}
}
if(st.isEmpty()){
ans.add(s);
return true;
}
return false;
}
}
//上面的代码直接改成dfs也可以。
Set<String> vis=new HashSet<String>();
char[] c={'(',')'};
public List<String> removeInvalidParentheses(String s) {
vis.add(s);
List<String> ans=new ArrayList<String>();
checkLeft(s,ans);
return new ArrayList<String>(ans);
}
public void checkLeft(String s,List<String> ans){
//delete right
Stack<Character> st=new Stack<Character>();
for(int i=0;i<s.length();++i){
if(s.charAt(i)==c[0]){
st.push(s.charAt(i));
}else if(s.charAt(i)==c[1]){
if(st.isEmpty()){
for(int j=i;j>=0;--j){
if(s.charAt(j)==c[1]){
String s1=s.substring(0,j)+s.substring(j+1);
if(!vis.contains(s1)){
vis.add(s1);
checkLeft(s1,ans);
}
}
}
return;
}else{
st.pop();
}
}
}
if(st.isEmpty()){
ans.add(s);
}
checkRight(s,ans);
}
public void checkRight(String s,List<String> ans){
//delete right
Stack<Character> st=new Stack<Character>();
st.clear();
for(int i=s.length()-1;i>=0;--i){
if(s.charAt(i)==c[1]){
st.push(s.charAt(i));
}else if(s.charAt(i)==c[0]){
if(st.isEmpty()){
for(int j=i;j<s.length();++j){
if(s.charAt(j)==c[0]){
String s1=s.substring(0,j)+s.substring(j+1);
if(!vis.contains(s1)){
vis.add(s1);
checkRight(s1,ans);
}
}
}
return;
}else{
st.pop();
}
}
}
if(st.isEmpty()){
if(!ans.contains(s)){
ans.add(s);
}
}
}
//dfs二:
public class Solution {
public List<String> removeInvalidParentheses(String s) {
int leftCnt=0;
int rightCnt=0;
//删除多余的左右括号
for(char cur:s.toCharArray()){
if(cur==c[0]){
++leftCnt;
}
if(cur==c[1]){
if(leftCnt>0){
--leftCnt;
}else{
++rightCnt;
}
}
}
Set<String> vis=new HashSet<String>();
List<String> ans=new ArrayList<String>();
vis.add(s);
delete(0,s,leftCnt,rightCnt,ans,vis);
Collections.reverse(ans); //将结果进行翻转
return ans;
}
public void delete(int idx,String s,int leftCnt,int rightCnt,List<String> ans,Set<String> vis){
if(leftCnt==0&&rightCnt==0){
if(check(s)){
ans.add(s);
}
return;
}
for(int i=idx;i<s.length();++i){
if(i!=idx&&s.charAt(i)==s.charAt(i-1)){ //重复括号不需要删除 该状态之前已经有了
continue;
}
if(leftCnt>0&&s.charAt(i)==c[0]){ //删除多余左括号
String s1=s.substring(0,i)+s.substring(i+1);
if(!vis.contains(s1)){
delete(i,s1,leftCnt-1,rightCnt,ans,vis);
}
}
if(rightCnt>0&&s.charAt(i)==c[1]){ //删除多余右括号
String s1=s.substring(0,i)+s.substring(i+1);
if(!vis.contains(s1)){
delete(i,s1,leftCnt,rightCnt-1,ans,vis);
}
}
}
}
public char[] c={'(',')'};
public boolean check(String s){
int match=0; //利用match模拟栈
for(char cur:s.toCharArray()){
if(cur==c[0]){
++match;
}else if(cur==c[1]){
--match;
}
if(match<0){
return false;
}
}
return match==0;
}
}