Skip to content

Commit 82fc208

Browse files
committedOct 4, 2022
feat: add solutions to lc problem: No.0301
No.0301.Remove Invalid Parentheses
1 parent b04e941 commit 82fc208

File tree

6 files changed

+400
-243
lines changed

6 files changed

+400
-243
lines changed
 

‎solution/0300-0399/0301.Remove Invalid Parentheses/README.md

+150-82
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,30 @@
4747

4848
<!-- 这里可写通用的实现逻辑 -->
4949

50-
DFS + 剪枝
50+
**方法一:DFS + 剪枝**
5151

52-
`ldel`, `rdel` 分别表示最少需要删除的 `(`, `)` 的个数。
52+
我们首先处理得到字符串 $s$ 待删除的左、右括号的最小数量,分别记为 $l$ 和 $r$。
53+
54+
然后我们设计一个递归函数 `dfs(i, l, r, lcnt, rcnt, t)`,其中:
55+
56+
- `i` 表示当前处理到字符串 $s$ 的第 $i$ 个字符;
57+
- `l``r` 分别表示剩余待删除的左、右括号的数量;
58+
- `t` 表示当前得到的字符串;
59+
- `lcnt``rcnt` 分别表示当前得到的字符串中左、右括号的数量。
60+
61+
递归函数的逻辑如下:
62+
63+
- 如果 `i` 等于字符串 $s$ 的长度,且 `l``r` 都等于 $0$,则将 `t` 加入答案数组中;
64+
- 如果剩余的待处理字符数 $n-i$ 小于剩余待删除的左右括号数量 $l+r$,或者当前得到的字符串中的左括号数量小于右括号数量,直接返回;
65+
- 如果当前字符是左括号,我们可以选择删除或者保留,如果删除,需要满足 $l \gt 0$,然后递归调用 `dfs(i+1, l-1, r, lcnt, rcnt, t)`
66+
- 如果当前字符是右括号,我们可以选择删除或者保留,如果删除,需要满足 $r \gt 0$,然后递归调用 `dfs(i+1, l, r-1, lcnt, rcnt, t)`
67+
- 如果选择保留当前字符,我们需要判断当前字符是左括号、右括号还是字母。如果是左括号,我们需要更新 `lcnt`,如果是右括号,我们需要更新 `rcnt`,然后递归调用 `dfs(i+1, l, r, lcnt, rcnt, t+s[i])`
68+
69+
我们调用 `dfs(0, l, r, 0, 0, "")`,搜索所有可能的字符串。
70+
71+
最后返回去重后的答案数组即可。
72+
73+
时间复杂度 $O(n\times 2^n)$,空间复杂度 $O(n)$。长度为 $n$ 的字符串有 $2^n$ 种可能的删除方式,每种删除方式需要 $O(n)$ 的时间复制字符串。因此总时间复杂度为 $O(n\times 2^n)$。
5374

5475
<!-- tabs:start -->
5576

@@ -60,36 +81,32 @@ DFS + 剪枝。
6081
```python
6182
class Solution:
6283
def removeInvalidParentheses(self, s: str) -> List[str]:
63-
def dfs(i, t, lcnt, rcnt, ldel, rdel):
64-
nonlocal tdel, ans
65-
if ldel * rdel < 0 or lcnt < rcnt or ldel + rdel > len(s) - i:
66-
return
67-
if ldel == 0 and rdel == 0:
68-
if len(s) - len(t) == tdel:
84+
def dfs(i, l, r, lcnt, rcnt, t):
85+
if i == n:
86+
if l == 0 and r == 0:
6987
ans.add(t)
70-
if i == len(s):
7188
return
72-
if s[i] == '(':
73-
dfs(i + 1, t, lcnt, rcnt, ldel - 1, rdel)
74-
dfs(i + 1, t + '(', lcnt + 1, rcnt, ldel, rdel)
75-
elif s[i] == ')':
76-
dfs(i + 1, t, lcnt, rcnt, ldel, rdel - 1)
77-
dfs(i + 1, t + ')', lcnt, rcnt + 1, ldel, rdel)
78-
else:
79-
dfs(i + 1, t + s[i], lcnt, rcnt, ldel, rdel)
80-
81-
ldel = rdel = 0
89+
if n - i < l + r or lcnt < rcnt:
90+
return
91+
if s[i] == '(' and l:
92+
dfs(i + 1, l - 1, r, lcnt, rcnt, t)
93+
elif s[i] == ')' and r:
94+
dfs(i + 1, l, r - 1, lcnt, rcnt, t)
95+
dfs(i + 1, l, r, lcnt + (s[i] == '('),
96+
rcnt + (s[i] == ')'), t + s[i])
97+
98+
l = r = 0
8299
for c in s:
83100
if c == '(':
84-
ldel += 1
101+
l += 1
85102
elif c == ')':
86-
if ldel == 0:
87-
rdel += 1
103+
if l:
104+
l -= 1
88105
else:
89-
ldel -= 1
90-
tdel = ldel + rdel
106+
r += 1
91107
ans = set()
92-
dfs(0, '', 0, 0, ldel, rdel)
108+
n = len(s)
109+
dfs(0, l, r, 0, 0, '')
93110
return list(ans)
94111
```
95112

@@ -99,52 +116,49 @@ class Solution:
99116

100117
```java
101118
class Solution {
102-
private int tdel;
103119
private String s;
104-
private Set<String> ans;
120+
private int n;
121+
private Set<String> ans = new HashSet<>();
105122

106123
public List<String> removeInvalidParentheses(String s) {
107-
int ldel = 0, rdel = 0;
124+
this.s = s;
125+
this.n = s.length();
126+
int l = 0, r = 0;
108127
for (char c : s.toCharArray()) {
109128
if (c == '(') {
110-
++ldel;
129+
++l;
111130
} else if (c == ')') {
112-
if (ldel == 0) {
113-
++rdel;
131+
if (l > 0) {
132+
--l;
114133
} else {
115-
--ldel;
134+
++r;
116135
}
117136
}
118137
}
119-
tdel = ldel + rdel;
120-
this.s = s;
121-
ans = new HashSet<>();
122-
dfs(0, "", 0, 0, ldel, rdel);
138+
dfs(0, l, r, 0, 0, "");
123139
return new ArrayList<>(ans);
124140
}
125141

126-
private void dfs(int i, String t, int lcnt, int rcnt, int ldel, int rdel) {
127-
if (ldel * rdel < 0 || lcnt < rcnt || ldel + rdel > s.length() - i) {
128-
return;
129-
}
130-
if (ldel == 0 && rdel == 0) {
131-
if (s.length() - t.length() == tdel) {
142+
private void dfs(int i, int l, int r, int lcnt, int rcnt, String t) {
143+
if (i == n) {
144+
if (l == 0 && r == 0) {
132145
ans.add(t);
133146
}
147+
return;
134148
}
135-
if (i == s.length()) {
149+
if (n - i < l + r || lcnt < rcnt) {
136150
return;
137151
}
138152
char c = s.charAt(i);
139-
if (c == '(') {
140-
dfs(i + 1, t, lcnt, rcnt, ldel - 1, rdel);
141-
dfs(i + 1, t + String.valueOf(c), lcnt + 1, rcnt, ldel, rdel);
142-
} else if (c == ')') {
143-
dfs(i + 1, t, lcnt, rcnt, ldel, rdel - 1);
144-
dfs(i + 1, t + String.valueOf(c), lcnt, rcnt + 1, ldel, rdel);
145-
} else {
146-
dfs(i + 1, t + String.valueOf(c), lcnt, rcnt, ldel, rdel);
153+
if (c == '(' && l > 0) {
154+
dfs(i + 1, l - 1, r, lcnt, rcnt, t);
147155
}
156+
if (c == ')' && r > 0) {
157+
dfs(i + 1, l, r - 1, lcnt, rcnt, t);
158+
}
159+
int x = c == '(' ? 1 : 0;
160+
int y = c == ')' ? 1 : 0;
161+
dfs(i + 1, l, r, lcnt + x, rcnt + y, t + c);
148162
}
149163
}
150164
```
@@ -155,44 +169,98 @@ class Solution {
155169
class Solution {
156170
public:
157171
vector<string> removeInvalidParentheses(string s) {
158-
int ldel = 0, rdel = 0;
159-
for (char c : s) {
160-
if (c == '(')
161-
++ldel;
162-
else if (c == ')') {
163-
if (ldel == 0)
164-
++rdel;
165-
else
166-
--ldel;
172+
unordered_set<string> ans;
173+
int l = 0, r = 0, n = s.size();
174+
for (char& c : s) {
175+
if (c == '(') {
176+
++l;
177+
} else if (c == ')') {
178+
if (l) {
179+
--l;
180+
} else {
181+
++r;
182+
}
167183
}
168184
}
169-
int tdel = ldel + rdel;
170-
unordered_set<string> ans;
171-
dfs(0, "", s, 0, 0, ldel, rdel, tdel, ans);
172-
vector<string> res;
173-
res.assign(ans.begin(), ans.end());
174-
return res;
175-
}
185+
function<void(int, int, int, int, int, string)> dfs;
186+
dfs = [&](int i, int l, int r, int lcnt, int rcnt, string t) {
187+
if (i == n) {
188+
if (l == 0 && r == 0) {
189+
ans.insert(t);
190+
}
191+
return;
192+
}
193+
if (n - i < l + r || lcnt < rcnt) {
194+
return;
195+
}
196+
if (s[i] == '(' && l) {
197+
dfs(i + 1, l - 1, r, lcnt, rcnt, t);
198+
}
199+
if (s[i] == ')' && r) {
200+
dfs(i + 1, l, r - 1, lcnt, rcnt, t);
201+
}
202+
int x = s[i] == '(' ? 1 : 0;
203+
int y = s[i] == ')' ? 1 : 0;
204+
dfs(i + 1, l, r, lcnt + x, rcnt + y, t + s[i]);
205+
};
176206

177-
void dfs(int i, string t, string s, int lcnt, int rcnt, int ldel, int rdel, int tdel, unordered_set<string>& ans) {
178-
if (ldel * rdel < 0 || lcnt < rcnt || ldel + rdel > s.size() - i) return;
179-
if (ldel == 0 && rdel == 0) {
180-
if (s.size() - t.size() == tdel) ans.insert(t);
181-
}
182-
if (i == s.size()) return;
183-
if (s[i] == '(') {
184-
dfs(i + 1, t, s, lcnt, rcnt, ldel - 1, rdel, tdel, ans);
185-
dfs(i + 1, t + s[i], s, lcnt + 1, rcnt, ldel, rdel, tdel, ans);
186-
} else if (s[i] == ')') {
187-
dfs(i + 1, t, s, lcnt, rcnt, ldel, rdel - 1, tdel, ans);
188-
dfs(i + 1, t + s[i], s, lcnt, rcnt + 1, ldel, rdel, tdel, ans);
189-
} else {
190-
dfs(i + 1, t + s[i], s, lcnt, rcnt, ldel, rdel, tdel, ans);
191-
}
207+
dfs(0, l, r, 0, 0, "");
208+
return vector<string>(ans.begin(), ans.end());
192209
}
193210
};
194211
```
195212

213+
### **Go**
214+
215+
```go
216+
func removeInvalidParentheses(s string) []string {
217+
vis := map[string]bool{}
218+
l, r, n := 0, 0, len(s)
219+
for _, c := range s {
220+
if c == '(' {
221+
l++
222+
} else if c == ')' {
223+
if l > 0 {
224+
l--
225+
} else {
226+
r++
227+
}
228+
}
229+
}
230+
var dfs func(i, l, r, lcnt, rcnt int, t string)
231+
dfs = func(i, l, r, lcnt, rcnt int, t string) {
232+
if i == n {
233+
if l == 0 && r == 0 {
234+
vis[t] = true
235+
}
236+
return
237+
}
238+
if n-i < l+r || lcnt < rcnt {
239+
return
240+
}
241+
if s[i] == '(' && l > 0 {
242+
dfs(i+1, l-1, r, lcnt, rcnt, t)
243+
}
244+
if s[i] == ')' && r > 0 {
245+
dfs(i+1, l, r-1, lcnt, rcnt, t)
246+
}
247+
x, y := 0, 0
248+
if s[i] == '(' {
249+
x = 1
250+
} else if s[i] == ')' {
251+
y = 1
252+
}
253+
dfs(i+1, l, r, lcnt+x, rcnt+y, t+string(s[i]))
254+
}
255+
dfs(0, l, r, 0, 0, "")
256+
ans := make([]string, 0, len(vis))
257+
for v := range vis {
258+
ans = append(ans, v)
259+
}
260+
return ans
261+
}
262+
```
263+
196264
### **...**
197265

198266
```

0 commit comments

Comments
 (0)