47
47
48
48
<!-- 这里可写通用的实现逻辑 -->
49
49
50
- DFS + 剪枝。
50
+ ** 方法一: DFS + 剪枝**
51
51
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)$。
53
74
54
75
<!-- tabs:start -->
55
76
@@ -60,36 +81,32 @@ DFS + 剪枝。
60
81
``` python
61
82
class Solution :
62
83
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 :
69
87
ans.add(t)
70
- if i == len (s):
71
88
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
82
99
for c in s:
83
100
if c == ' (' :
84
- ldel += 1
101
+ l += 1
85
102
elif c == ' )' :
86
- if ldel == 0 :
87
- rdel + = 1
103
+ if l :
104
+ l - = 1
88
105
else :
89
- ldel -= 1
90
- tdel = ldel + rdel
106
+ r += 1
91
107
ans = set ()
92
- dfs(0 , ' ' , 0 , 0 , ldel, rdel)
108
+ n = len (s)
109
+ dfs(0 , l, r, 0 , 0 , ' ' )
93
110
return list (ans)
94
111
```
95
112
@@ -99,52 +116,49 @@ class Solution:
99
116
100
117
``` java
101
118
class Solution {
102
- private int tdel;
103
119
private String s;
104
- private Set<String > ans;
120
+ private int n;
121
+ private Set<String > ans = new HashSet<> ();
105
122
106
123
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 ;
108
127
for (char c : s. toCharArray()) {
109
128
if (c == ' (' ) {
110
- ++ ldel ;
129
+ ++ l ;
111
130
} else if (c == ' )' ) {
112
- if (ldel == 0 ) {
113
- ++ rdel ;
131
+ if (l > 0 ) {
132
+ -- l ;
114
133
} else {
115
- -- ldel ;
134
+ ++ r ;
116
135
}
117
136
}
118
137
}
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 , " " );
123
139
return new ArrayList<> (ans);
124
140
}
125
141
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 ) {
132
145
ans. add(t);
133
146
}
147
+ return ;
134
148
}
135
- if (i == s . length() ) {
149
+ if (n - i < l + r || lcnt < rcnt ) {
136
150
return ;
137
151
}
138
152
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);
147
155
}
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);
148
162
}
149
163
}
150
164
```
@@ -155,44 +169,98 @@ class Solution {
155
169
class Solution {
156
170
public:
157
171
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
+ }
167
183
}
168
184
}
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
+ };
176
206
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());
192
209
}
193
210
};
194
211
```
195
212
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
+
196
264
### ** ...**
197
265
198
266
```
0 commit comments