@@ -49,22 +49,388 @@ iterator.hasNext(); // 返回 false
49
49
50
50
<!-- 这里可写通用的实现逻辑 -->
51
51
52
+ ** 方法一:DFS 回溯**
53
+
54
+ 我们通过 $DFS$ 枚举,预处理生成所有长度为 $combinationLength$ 的字符串,存放到 $cs$ 数组中。
55
+
56
+ ** 方法二:二进制编码**
57
+
58
+ 我们看个例子,对于 $abcd$,若 $combinationLength$ 为 2,则 $cs$ 就是 $ab, ac, ad, bc, bd, cd, ...$。
59
+
60
+ 对应的二进制数为:
61
+
62
+ ```
63
+ 1100
64
+ 1010
65
+ 1001
66
+ 0110
67
+ 0101
68
+ 0011
69
+ ...
70
+ ```
71
+
72
+ 观察到上述规律后,我们依次按照二进制编码从大到小的规律,将所有字符串依次求出。
73
+
74
+ 所谓的长度 $combinationLength$,只需要满足二进制编码中 $1$ 的个数满足要求即可。
75
+
52
76
<!-- tabs:start -->
53
77
54
78
### ** Python3**
55
79
56
80
<!-- 这里可写当前语言的特殊实现逻辑 -->
57
81
58
82
``` python
83
+ class CombinationIterator :
84
+
85
+ def __init__ (self , characters : str , combinationLength : int ):
86
+ def dfs (i ):
87
+ if len (t) == combinationLength:
88
+ cs.append(' ' .join(t))
89
+ return
90
+ if i == n:
91
+ return
92
+ t.append(characters[i])
93
+ dfs(i + 1 )
94
+ t.pop()
95
+ dfs(i + 1 )
96
+
97
+ cs = []
98
+ n = len (characters)
99
+ t = []
100
+ dfs(0 )
101
+ self .cs = cs
102
+ self .idx = 0
103
+
104
+
105
+ def next (self ) -> str :
106
+ ans = self .cs[self .idx]
107
+ self .idx += 1
108
+ return ans
109
+
110
+ def hasNext (self ) -> bool :
111
+ return self .idx < len (self .cs)
112
+
59
113
114
+ # Your CombinationIterator object will be instantiated and called as such:
115
+ # obj = CombinationIterator(characters, combinationLength)
116
+ # param_1 = obj.next()
117
+ # param_2 = obj.hasNext()
118
+ ```
119
+
120
+ ``` python
121
+ class CombinationIterator :
122
+
123
+ def __init__ (self , characters : str , combinationLength : int ):
124
+ self .curr = (1 << len (characters)) - 1
125
+ self .size = combinationLength
126
+ self .cs = characters[::- 1 ]
127
+
128
+ def next (self ) -> str :
129
+ while self .curr >= 0 and self .curr.bit_count() != self .size:
130
+ self .curr -= 1
131
+ ans = []
132
+ for i in range (len (self .cs)):
133
+ if (self .curr >> i) & 1 :
134
+ ans.append(self .cs[i])
135
+ self .curr -= 1
136
+ return ' ' .join(ans[::- 1 ])
137
+
138
+ def hasNext (self ) -> bool :
139
+ while self .curr >= 0 and self .curr.bit_count() != self .size:
140
+ self .curr -= 1
141
+ return self .curr >= 0
142
+
143
+
144
+ # Your CombinationIterator object will be instantiated and called as such:
145
+ # obj = CombinationIterator(characters, combinationLength)
146
+ # param_1 = obj.next()
147
+ # param_2 = obj.hasNext()
60
148
```
61
149
62
150
### ** Java**
63
151
64
152
<!-- 这里可写当前语言的特殊实现逻辑 -->
65
153
66
154
``` java
155
+ class CombinationIterator {
156
+ private int n;
157
+ private int combinationLength;
158
+ private String characters;
159
+ private StringBuilder t = new StringBuilder ();
160
+ private List<String > cs = new ArrayList<> ();
161
+ private int idx = 0 ;
162
+
163
+ public CombinationIterator (String characters , int combinationLength ) {
164
+ n = characters. length();
165
+ this . combinationLength = combinationLength;
166
+ this . characters = characters;
167
+ dfs(0 );
168
+ }
169
+
170
+ public String next () {
171
+ return cs. get(idx++ );
172
+ }
173
+
174
+ public boolean hasNext () {
175
+ return idx < cs. size();
176
+ }
177
+
178
+ private void dfs (int i ) {
179
+ if (t. length() == combinationLength) {
180
+ cs. add(t. toString());
181
+ return ;
182
+ }
183
+ if (i == n) {
184
+ return ;
185
+ }
186
+ t. append(characters. charAt(i));
187
+ dfs(i + 1 );
188
+ t. deleteCharAt(t. length() - 1 );
189
+ dfs(i + 1 );
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Your CombinationIterator object will be instantiated and called as such:
195
+ * CombinationIterator obj = new CombinationIterator(characters, combinationLength);
196
+ * String param_1 = obj.next();
197
+ * boolean param_2 = obj.hasNext();
198
+ */
199
+ ```
200
+
201
+ ``` java
202
+ class CombinationIterator {
203
+ private int curr;
204
+ private int size;
205
+ private char [] cs;
206
+
207
+ public CombinationIterator (String characters , int combinationLength ) {
208
+ int n = characters. length();
209
+ curr = (1 << n) - 1 ;
210
+ size = combinationLength;
211
+ cs = new char [n];
212
+ for (int i = 0 ; i < n; ++ i) {
213
+ cs[i] = characters. charAt(n - i - 1 );
214
+ }
215
+ }
216
+
217
+ public String next () {
218
+ while (curr >= 0 && Integer . bitCount(curr) != size) {
219
+ -- curr;
220
+ }
221
+ StringBuilder ans = new StringBuilder ();
222
+ for (int i = 0 ; i < cs. length; ++ i) {
223
+ if (((curr >> i) & 1 ) == 1 ) {
224
+ ans. append(cs[i]);
225
+ }
226
+ }
227
+ -- curr;
228
+ return ans. reverse(). toString();
229
+ }
230
+
231
+ public boolean hasNext () {
232
+ while (curr >= 0 && Integer . bitCount(curr) != size) {
233
+ -- curr;
234
+ }
235
+ return curr >= 0 ;
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Your CombinationIterator object will be instantiated and called as such:
241
+ * CombinationIterator obj = new CombinationIterator(characters, combinationLength);
242
+ * String param_1 = obj.next();
243
+ * boolean param_2 = obj.hasNext();
244
+ */
245
+ ```
246
+
247
+ ### ** C++**
248
+
249
+ ``` cpp
250
+ class CombinationIterator {
251
+ public:
252
+ string characters;
253
+ vector<string > cs;
254
+ int idx;
255
+ int n;
256
+ int combinationLength;
257
+ string t;
258
+
259
+ CombinationIterator(string characters, int combinationLength) {
260
+ idx = 0;
261
+ n = characters.size();
262
+ this->characters = characters;
263
+ this->combinationLength = combinationLength;
264
+ dfs(0);
265
+ }
266
+
267
+ string next () {
268
+ return cs[idx++];
269
+ }
270
+
271
+ bool hasNext() {
272
+ return idx < cs.size();
273
+ }
274
+
275
+ void dfs(int i) {
276
+ if (t.size() == combinationLength) {
277
+ cs.push_back(t);
278
+ return;
279
+ }
280
+ if (i == n) return;
281
+ t.push_back(characters[i]);
282
+ dfs (i + 1);
283
+ t.pop_back();
284
+ dfs(i + 1);
285
+ }
286
+ };
287
+
288
+ /* *
289
+ * Your CombinationIterator object will be instantiated and called as such:
290
+ * CombinationIterator* obj = new CombinationIterator(characters, combinationLength);
291
+ * string param_1 = obj->next();
292
+ * bool param_2 = obj->hasNext();
293
+ */
294
+ ```
295
+
296
+ ``` cpp
297
+ class CombinationIterator {
298
+ public:
299
+ int size;
300
+ string cs;
301
+ int curr;
302
+
303
+ CombinationIterator(string characters, int combinationLength) {
304
+ int n = characters.size();
305
+ curr = (1 << n) - 1;
306
+ reverse(characters.begin(), characters.end());
307
+ cs = characters;
308
+ size = combinationLength;
309
+ }
310
+
311
+ string next () {
312
+ while (curr >= 0 && __builtin_popcount(curr) != size) --curr;
313
+ string ans;
314
+ for (int i = 0; i < cs.size(); ++i) {
315
+ if ((curr >> i) & 1) {
316
+ ans += cs[i];
317
+ }
318
+ }
319
+ reverse (ans.begin(), ans.end());
320
+ --curr;
321
+ return ans;
322
+ }
323
+
324
+ bool hasNext() {
325
+ while (curr >= 0 && __builtin_popcount(curr) != size) --curr;
326
+ return curr >= 0;
327
+ }
328
+ };
329
+
330
+ /* *
331
+ * Your CombinationIterator object will be instantiated and called as such:
332
+ * CombinationIterator* obj = new CombinationIterator(characters, combinationLength);
333
+ * string param_1 = obj->next();
334
+ * bool param_2 = obj->hasNext();
335
+ */
336
+ ```
337
+
338
+ ### ** Go**
339
+
340
+ ``` go
341
+ type CombinationIterator struct {
342
+ cs []string
343
+ idx int
344
+ }
345
+
346
+ func Constructor (characters string , combinationLength int ) CombinationIterator {
347
+ t := []byte {}
348
+ n := len (characters)
349
+ cs := []string {}
350
+ var dfs func (int )
351
+ dfs = func (i int ) {
352
+ if len (t) == combinationLength {
353
+ cs = append (cs, string (t))
354
+ return
355
+ }
356
+ if i == n {
357
+ return
358
+ }
359
+ t = append (t, characters[i])
360
+ dfs (i + 1 )
361
+ t = t[:len (t)-1 ]
362
+ dfs (i + 1 )
363
+ }
364
+ dfs (0 )
365
+ return CombinationIterator{cs, 0 }
366
+ }
367
+
368
+ func (this *CombinationIterator ) Next () string {
369
+ ans := this.cs [this.idx ]
370
+ this.idx ++
371
+ return ans
372
+ }
373
+
374
+ func (this *CombinationIterator ) HasNext () bool {
375
+ return this.idx < len (this.cs )
376
+ }
377
+
378
+ /* *
379
+ * Your CombinationIterator object will be instantiated and called as such:
380
+ * obj := Constructor(characters, combinationLength);
381
+ * param_1 := obj.Next();
382
+ * param_2 := obj.HasNext();
383
+ */
384
+ ```
385
+
386
+ ``` go
387
+ type CombinationIterator struct {
388
+ curr int
389
+ size int
390
+ cs []byte
391
+ }
392
+
393
+ func Constructor (characters string , combinationLength int ) CombinationIterator {
394
+ n := len (characters)
395
+ curr := (1 << n) - 1
396
+ size := combinationLength
397
+ cs := make ([]byte , n)
398
+ for i := range characters {
399
+ cs[n-i-1 ] = characters[i]
400
+ }
401
+ return CombinationIterator{curr, size, cs}
402
+ }
403
+
404
+ func (this *CombinationIterator ) Next () string {
405
+ for this.curr >= 0 && bits.OnesCount (uint (this.curr )) != this.size {
406
+ this.curr --
407
+ }
408
+ ans := []byte {}
409
+ for i := range this.cs {
410
+ if (this.curr >> i & 1 ) == 1 {
411
+ ans = append (ans, this.cs [i])
412
+ }
413
+ }
414
+ for i , j := 0 , len (ans)-1 ; i < j; i, j = i+1 , j-1 {
415
+ ans[i], ans[j] = ans[j], ans[i]
416
+ }
417
+ this.curr --
418
+ return string (ans)
419
+ }
420
+
421
+ func (this *CombinationIterator ) HasNext () bool {
422
+ for this.curr >= 0 && bits.OnesCount (uint (this.curr )) != this.size {
423
+ this.curr --
424
+ }
425
+ return this.curr >= 0
426
+ }
67
427
428
+ /* *
429
+ * Your CombinationIterator object will be instantiated and called as such:
430
+ * obj := Constructor(characters, combinationLength);
431
+ * param_1 := obj.Next();
432
+ * param_2 := obj.HasNext();
433
+ */
68
434
```
69
435
70
436
### ** ...**
0 commit comments