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 )
.
Examples:
"()())()" -> ["()()()", "(())()"]
"(a)())()" -> ["(a)()()", "(a())()"]
")(" -> [""]
Credits:
Special thanks to @hpplayer for adding this problem and creating all test cases.
题目链接:https://leetcode.com/problems/remove-invalid-parentheses/
public class Solution {
class Data {
String s;
int cnt;
Data(String s, int cnt) {
this.s = s;
this.cnt = cnt;
}
}
public List<String> removeInvalidParentheses(String s) {
Queue<Data> q = new LinkedList<>();
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
q.add(new Data(s, 0));
int cnt = Integer.MAX_VALUE;
boolean flag = false;
while (q.size() > 0) {
Data cur = q.poll();
if (isValid(cur.s)) {
if (!flag) {
flag = true;
cnt = cur.cnt;
}
if (cur.cnt == cnt) {
list.add(cur.s);
}
else {
return list;
}
}
int len = cur.s.length();
for (int i = 0; i < len; i ++) {
if(cur.s.charAt(i) == '(' || cur.s.charAt(i) == ')') {
String tmp = cur.s.substring(0, i) + cur.s.substring(i + 1, len);
if (!set.contains(tmp)) {
set.add(tmp);
q.add(new Data(tmp, cur.cnt + 1));
}
}
}
}
return list;
}
boolean isValid(String s) {
int len = s.length();
int l = 0;
for (int i = 0; i < len; i ++) {
if (s.charAt(i) == '(') {
l ++;
}
else if (s.charAt(i) == ')'){
l --;
}
if (l < 0) {
return false;
}
}
return l == 0;
}
}
其实发现这个Data类是多余的,或者说不需要记录cnt,由于BFS是广度优先,或者说一层一层的搜,所以某层求得解后标记一下即可,这样又得到了95ms的代码
public class Solution {
public List<String> removeInvalidParentheses(String s) {
Queue<String> q = new LinkedList<>();
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
boolean flag = false;
q.add(s);
while (!q.isEmpty()) {
String cur = q.poll();
if (isValid(cur)) {
list.add(cur);
flag = true;
if (q.isEmpty()) {
return list;
}
}
if (!flag) {
int len = cur.length();
for (int i = 0; i < len; i ++) {
if(cur.charAt(i) == '(' || cur.charAt(i) == ')') {
String nxt = cur.substring(0, i) + cur.substring(i + 1, len);
if (set.add(nxt)) {
q.add(nxt);
}
}
}
}
}
return list;
}
boolean isValid(String s) {
int len = s.length();
int l = 0;
for (int i = 0; i < len; i ++) {
if (s.charAt(i) == '(') {
l ++;
}
else if (s.charAt(i) == ')'){
l --;
}
if (l < 0) {
return false;
}
}
return l == 0;
}
}
接着可以发现若合法,那么第一个括号必然是左括号,最后一个必然是右括号,这里预处理一下变成42ms,在枚举删除点的时候,连续重复的括号只需要删除一个,这里判断一下变成33ms,其实还有能优化的地方。。。discuss里有3ms DFS的大神。。。
public class Solution {
//42ms
public String removeHelper(String s) {
int len = s.length();
if (len == 0) {
return s;
}
int i = 0, j = len - 1;
while (i < j && s.charAt(i) == ')') {
i ++;
}
while (i < j && s.charAt(j) == '(') {
j --;
}
return s.substring(i, j + 1);
}
public List<String> removeInvalidParentheses(String s) {
Queue<String> q = new LinkedList<>();
List<String> list = new ArrayList<>();
Set<String> set = new HashSet<>();
boolean flag = false;
q.add(removeHelper(s));
while (!q.isEmpty()) {
String cur = q.poll();
if (isValid(cur)) {
list.add(cur);
flag = true;
if (q.isEmpty()) {
return list;
}
}
if (!flag) {
int len = cur.length();
for (int i = 0; i < len; i ++) {
if(cur.charAt(i) == '(' || cur.charAt(i) == ')') {
//33ms
if (i + 1 < len && cur.charAt(i) == cur.charAt(i + 1)) {
continue;
}
String nxt = cur.substring(0, i) + cur.substring(i + 1, len);
if (set.add(nxt)) {
q.add(nxt);
}
}
}
}
}
return list;
}
boolean isValid(String s) {
int len = s.length();
int l = 0;
for (int i = 0; i < len; i ++) {
if (s.charAt(i) == '(') {
l ++;
}
else if (s.charAt(i) == ')'){
l --;
}
if (l < 0) {
return false;
}
}
return l == 0;
}
}