Skip to content

Commit e797b43

Browse files
committed
feat: add solutions to lc problem: No.1286
No.1286.Iterator for Combination
1 parent 6828938 commit e797b43

File tree

6 files changed

+864
-0
lines changed

6 files changed

+864
-0
lines changed

solution/1200-1299/1286.Iterator for Combination/README.md

Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,388 @@ iterator.hasNext(); // 返回 false
4949

5050
<!-- 这里可写通用的实现逻辑 -->
5151

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+
5276
<!-- tabs:start -->
5377

5478
### **Python3**
5579

5680
<!-- 这里可写当前语言的特殊实现逻辑 -->
5781

5882
```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+
59113

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()
60148
```
61149

62150
### **Java**
63151

64152
<!-- 这里可写当前语言的特殊实现逻辑 -->
65153

66154
```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+
}
67427

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+
*/
68434
```
69435

70436
### **...**

0 commit comments

Comments
 (0)