Sponsored
Sponsored
In this approach, we use an internal buffer variable to store the next element of the iterator. The key idea is to always keep the next element ready in this buffer when operations like `peek` are called. The `peek` method can return this buffered value, and the `next` method will return the buffered value while simultaneously updating the buffer with the new next element from the iterator.
Time Complexity: O(1) for all operations.
Space Complexity: O(1), as we only store single elements.
1import java.util.Iterator;
2
3class PeekingIterator implements Iterator<Integer> {
4 private Iterator<Integer> iterator;
5 private Integer nextElement;
6
7 public PeekingIterator(Iterator<Integer> iterator) {
8 this.iterator = iterator;
9 if (iterator.hasNext()) {
10 nextElement = iterator.next();
11 }
12 }
13
14 public Integer peek() {
15 return nextElement;
16 }
17
18 @Override
19 public Integer next() {
20 Integer current = nextElement;
21 nextElement = iterator.hasNext() ? iterator.next() : null;
22 return current;
23 }
24
25 @Override
26 public boolean hasNext() {
27 return nextElement != null;
28 }
29}
The Java solution implements the Iterator interface and keeps a private variable `nextElement` to cache the next element. The constructor initializes the `nextElement` by fetching the first element from the iterator if available. Similar to Python, `peek` returns the cached value, and `next` updates the cache with the next iterator value. `hasNext` checks if `nextElement` is null.
This approach leverages the iterator's facility by explicitly controlling its movement and caching the result for future references. It reads the next element so that `peek` can access it but avoids advancing through a list prematurely. Operations are efficient with constant time complexity for each of `peek`, `next`, and `hasNext`.
Time Complexity: O(1) for all operations.
Space Complexity: O(1).
1using System.Collections.Generic;
2
3public class PeekingIterator {
4 private IEnumerator<int> iterator;
5 private bool hasPeeked;
private int nextElement;
public PeekingIterator(IEnumerator<int> iterator) {
this.iterator = iterator;
this.hasPeeked = false;
}
public int Peek() {
if (!hasPeeked) {
iterator.MoveNext();
nextElement = iterator.Current;
hasPeeked = true;
}
return nextElement;
}
public int Next() {
if (!hasPeeked) {
iterator.MoveNext();
return iterator.Current;
}
hasPeeked = false;
return nextElement;
}
public bool HasNext() {
return hasPeeked || iterator.MoveNext();
}
}
For C#, we utilize the `IEnumerator` interface to iterate through the collection. The `hasPeeked` boolean flags whether the iterator has fetched the next element. We implement `Peek()` to fetch and store the next element if not already done. `Next()` checks if we've peeked; if not, it uses `MoveNext()` to advance. `HasNext()` determines if there are more elements to traverse through `hasPeeked` or using `MoveNext()`.