Implement a Removable Nested-List Iterator
AirbnbSoftware Engineer · Technical ScreenLast updated
Design and implement a nested-list iterator supporting `hasNext`, `next`, and an in-place `remove` operation that alters the original data structure.
Problem Statement
Implement an iterator class, NestedIterator, that traverses an arbitrarily nested list of integers (where each element can either be an integer or another list of integers) and supports in-place deletion.
The iterator must implement the following methods:
__init__(nested_list: list): Initializes the iterator with the reference to the original nested list.next() -> int: Returns the next integer in the depth-first traversal and advances the pointer. RaisesRuntimeErrorif there are no more integers.hasNext() -> bool: ReturnsTrueif there are still integers remaining to visit, orFalseotherwise. Multiple consecutive calls tohasNext()must be idempotent and must not skip any elements.remove() -> None: Deletes the integer returned by the most recent call tonext()directly from the underlying nested list. Callingremove()beforenext()has been called, or callingremove()twice without an interveningnext()call, must raiseRuntimeError.
Any deletions must be reflected in the original nested_list passed into the constructor.
Interface
class NestedIterator:
def __init__(self, nested_list: list):
pass
def next(self) -> int:
pass
def hasNext(self) -> bool:
pass
def remove(self) -> None:
pass
Examples
Example 1
data = [[1, 2], [], [3]]
it = NestedIterator(data)
assert it.hasNext() == True
assert it.next() == 1
it.remove() # Removes 1 from data
assert it.next() == 2
assert it.next() == 3
assert it.hasNext() == False
# The original structure reflects the removal:
assert data == [[2], [], [3]]
Example 2
data = [1, [[]], [2, 3]]
it = NestedIterator(data)
assert it.next() == 1
assert it.next() == 2
it.remove() # Removes 2
# it.remove() # Would raise RuntimeError if called again immediately
assert it.next() == 3
assert data == [1, [[]], [3]]
Constraints
- Total number of integers and sublists across all levels is at most
10^5. - Integer values are in the range
[-10^9, 10^9]. - The maximum depth of nesting is at most
10^3. - Auxiliary space complexity (excluding the input itself) should be
O(D), whereDis the maximum depth of nesting.
Edge Cases to Consider
- Consecutive empty lists at any depth (e.g.,
[[], [[]], 1]). - Calling
hasNext()multiple times in a row before callingnext(). - Calling
remove()at the beginning before anynext()call. - Calling
remove()on the last element in a sublist or the overall list.
Hints
Hint 1
Maintain a stack of references `(current_list, current_index)` to track your traversal path without copying the data.
Hint 2
Make `hasNext()` prepare the next valid integer by advancing past empty lists and descending into nested sublists as needed.
Hint 3
When `remove()` deletes an item at `index`, decrement that level's index pointer by 1 so the next forward step does not skip the adjacent element.
Follow-up questions
- How would you support a `peek()` operation without altering the legal calling sequence for `remove()`?
- If an entire sublist becomes empty as a result of deletions, should it be removed from its parent? How would you implement that cascade?
- How would you make this iterator thread-safe if another thread could concurrently read or write to `nested_list`?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.