Skip to content

Commit 5d9fb63

Browse files
committed
Add solution of NestedIterator task. But one of cases not covered yet
1 parent 388e40c commit 5d9fb63

File tree

2 files changed

+199
-0
lines changed

2 files changed

+199
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package by.andd3dfx.iterators;
2+
3+
import java.util.ArrayDeque;
4+
import java.util.Deque;
5+
import java.util.Iterator;
6+
import java.util.List;
7+
import java.util.NoSuchElementException;
8+
9+
/**
10+
* <pre>
11+
* You are given a nested list of integers nestedList. Each element is either an integer or a list whose elements may also be integers or other lists. Implement an iterator to flatten it.
12+
*
13+
* Implement the NestedIterator class:
14+
*
15+
* NestedIterator(List<NestedInteger> nestedList) Initializes the iterator with the nested list nestedList.
16+
* int next() Returns the next integer in the nested list.
17+
* boolean hasNext() Returns true if there are still some integers in the nested list and false otherwise.
18+
*
19+
* Your code will be tested with the following pseudocode:
20+
*
21+
* initialize iterator with nestedList
22+
* res = []
23+
* while iterator.hasNext()
24+
* append iterator.next() to the end of res
25+
* return res
26+
*
27+
* If res matches the expected flattened list, then your code will be judged as correct.
28+
*
29+
* Example 1:
30+
* Input: nestedList = [[1,1],2,[1,1]]
31+
* Output: [1,1,2,1,1]
32+
* Explanation: By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,1,2,1,1].
33+
*
34+
* Example 2:
35+
* Input: nestedList = [1,[4,[6]]]
36+
* Output: [1,4,6]
37+
* Explanation: By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,4,6].
38+
* </pre>
39+
*/
40+
public class NestedIterator implements Iterator<Integer> {
41+
42+
private final Deque<Iterator<INestedInteger>> stack = new ArrayDeque<>();
43+
44+
public NestedIterator(List<INestedInteger> nestedList) {
45+
stack.push(nestedList.iterator());
46+
}
47+
48+
@Override
49+
public Integer next() {
50+
if (stack.isEmpty()) {
51+
throw new NoSuchElementException();
52+
}
53+
54+
var currentIterator = stack.peek();
55+
if (!currentIterator.hasNext()) {
56+
stack.pop();
57+
return next();
58+
}
59+
60+
INestedInteger object = currentIterator.next();
61+
if (object.isInteger()) {
62+
return object.getInteger();
63+
}
64+
stack.push(object.getList().iterator());
65+
return next();
66+
}
67+
68+
@Override
69+
public boolean hasNext() {
70+
if (stack.isEmpty()) {
71+
return false;
72+
}
73+
74+
var currentIterator = stack.peek();
75+
if (currentIterator.hasNext()) {
76+
return true;
77+
}
78+
stack.pop();
79+
return hasNext();
80+
}
81+
82+
public interface INestedInteger {
83+
84+
// @return true if this NestedInteger holds a single integer, rather than a nested list.
85+
boolean isInteger();
86+
87+
// @return the single integer that this NestedInteger holds, if it holds a single integer
88+
// Return null if this NestedInteger holds a nested list
89+
Integer getInteger();
90+
91+
// @return the nested list that this NestedInteger holds, if it holds a nested list
92+
// Return empty list if this NestedInteger holds a single integer
93+
List<INestedInteger> getList();
94+
}
95+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package by.andd3dfx.iterators;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import by.andd3dfx.iterators.NestedIterator.INestedInteger;
6+
import java.util.ArrayList;
7+
import java.util.Arrays;
8+
import java.util.List;
9+
import org.junit.Test;
10+
11+
public class NestedIteratorTest {
12+
13+
@Test
14+
public void testNextAndHasNext() {
15+
check(List.of(
16+
new NestedIntegerList(1, 1),
17+
new NestedInteger(2),
18+
new NestedIntegerList(1, 1)
19+
),
20+
List.of(1, 1, 2, 1, 1));
21+
22+
check(List.of(
23+
new NestedInteger(1),
24+
new NestedIntegerList(new NestedInteger(4), new NestedIntegerList(6))
25+
),
26+
List.of(1, 4, 6));
27+
28+
// TODO: fix implementation to support this case
29+
// check(List.of(
30+
// new NestedIntegerList()
31+
// ),
32+
// List.of());
33+
}
34+
35+
private void check(List<INestedInteger> incoming, List<Integer> outgoing) {
36+
var result = new ArrayList<>();
37+
38+
var nestedIterator = new NestedIterator(incoming);
39+
while (nestedIterator.hasNext()) {
40+
result.add(nestedIterator.next());
41+
}
42+
43+
assertThat(result).isEqualTo(outgoing);
44+
}
45+
46+
private static class NestedInteger implements INestedInteger {
47+
48+
private final Integer integer;
49+
50+
public NestedInteger(Integer integer) {
51+
this.integer = integer;
52+
}
53+
54+
@Override
55+
public boolean isInteger() {
56+
return true;
57+
}
58+
59+
@Override
60+
public Integer getInteger() {
61+
return integer;
62+
}
63+
64+
@Override
65+
public List<INestedInteger> getList() {
66+
throw new IllegalStateException();
67+
}
68+
}
69+
70+
private static class NestedIntegerList implements INestedInteger {
71+
72+
private final List<INestedInteger> list;
73+
74+
public NestedIntegerList() {
75+
list = new ArrayList<>();
76+
}
77+
78+
public NestedIntegerList(INestedInteger... values) {
79+
list = Arrays.stream(values).toList();
80+
}
81+
82+
public NestedIntegerList(int... values) {
83+
list = new ArrayList<>();
84+
for (var value : values) {
85+
list.add(new NestedInteger(value));
86+
}
87+
}
88+
89+
@Override
90+
public boolean isInteger() {
91+
return false;
92+
}
93+
94+
@Override
95+
public Integer getInteger() {
96+
throw new IllegalStateException();
97+
}
98+
99+
@Override
100+
public List<INestedInteger> getList() {
101+
return list;
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)