You are given a 2D vector (a list of lists of integers). Implement an iterator to flatten it into a 1D vector. The iterator should support two operations:
next()
: Returns the next element in the flattened vector.hasNext()
: Returns true
if there are more elements to iterate, false
otherwise.Example:
Input:
2D vector = [
[1, 2],
[3],
[4, 5, 6]
]
Iterator iterator = new Iterator(2D vector);
iterator.hasNext(); // returns true
iterator.next(); // returns 1
iterator.next(); // returns 2
iterator.hasNext(); // returns true
iterator.next(); // returns 3
iterator.hasNext(); // returns true
iterator.next(); // returns 4
iterator.hasNext(); // returns true
iterator.next(); // returns 5
iterator.hasNext(); // returns true
iterator.next(); // returns 6
iterator.hasNext(); // returns false
Constraints:
next()
and hasNext()
methods.next()
method should only be called if hasNext()
returns true
.How would you implement this, considering optimal time and space complexity? What are the potential edge cases to consider?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach completely unpacks the nested structure into a single, long list. It precomputes and stores everything from the start to avoid doing any calculations later when asked for the next element.
Here's how the algorithm would work step-by-step:
class Vector2D:
def __init__(self, vector_of_vectors):
# Flatten the 2D vector into a single list upon initialization.
self.flattened_list = []
for vector in vector_of_vectors:
for element in vector:
self.flattened_list.append(element)
# Keep track of the current index in the flattened list.
self.current_index = 0
def next(self):
# Return the next element in the flattened list and advance the index.
next_element = self.flattened_list[self.current_index]
self.current_index += 1
return next_element
def hasNext(self):
# Check if there are more elements in the flattened list.
return self.current_index < len(self.flattened_list)
We want to create a way to go through a list of lists as if it were one single list. The trick is to keep track of where we are in both the outer list and the inner list, advancing as needed.
Here's how the algorithm would work step-by-step:
class Vector2D:
def __init__(self, vector_of_vectors):
self.vector_of_vectors = vector_of_vectors
self.outer_index = 0
self.inner_index = 0
def next(self):
return self.vector_of_vectors[self.outer_index][self.inner_index]
def hasNext(self):
# Iterate to the next valid position
while self.outer_index < len(self.vector_of_vectors):
if self.inner_index < len(self.vector_of_vectors[self.outer_index]):
return True
# Move to the next vector if current is exhausted
else:
self.outer_index += 1
self.inner_index = 0
return False
Case | How to Handle |
---|---|
Input vector is null or empty. | The constructor should handle the null or empty input by initializing iterators to the end, so hasNext returns false immediately. |
Input vector contains empty inner vectors. | The hasNext method should advance the outer iterator past empty inner vectors before returning true, and next() should gracefully handle this. |
Input vector contains only one inner vector, which is also empty. | hasNext should return false immediately because there are no elements. |
Input vector with a very large number of inner vectors and elements, potentially exceeding memory limits for eager flattening. | The iterator approach handles this well as it only keeps track of current iterators and not a flattened copy. |
Consecutive empty inner vectors. | The hasNext() method must correctly skip over multiple consecutive empty inner vectors. |
Integer overflow if inner vectors contain very large integers. | The problem does not explicitly require dealing with integer overflow as it only asks for iteration, so we proceed assuming integer values are in range. |
All inner vectors are of size 1 | The iterator should be initialized properly and iterate through each of the single elements. |
Maximum size of the input 2D vector based on system memory limits | The iterative nature of the solution allows handling large inputs, but excessive memory allocation may cause issues. |