Introduction
LeetCode 284: Peeking Iterator is a classic object-oriented design problem. The task is to extend a given iterator so that it supports a peek()
operation that returns the next element without advancing the iterator.
This problem is often seen in system design interviews and API design challenges, especially when wrapping lower-level APIs into smarter components.
Problem Statement
Design an iterator that supports the peek()
operation — it returns the next element in the iteration without advancing the iterator. Implement the PeekingIterator
class that:
- Inherits from an existing
Iterator
class (assume it's already implemented).
- Adds a
peek()
method.
- Overrides
next()
and hasNext()
.
Example
python
Input: Iterator over [1,2,3]
Operations:
peek() → 1
next() → 1
next() → 2
peek() → 3
next() → 3
hasNext() → False
✅ Step-by-Step Solution
🧠 Core Idea
We need to add a peek()
function, which shows the next element without moving the iterator.
To achieve this:
- We cache the next element in a variable.
- When
peek()
is called, we simply return this cached value.
next()
returns the cached value and updates the cache with the next value (if any).
hasNext()
checks whether anything is left.
✅ Python Code
We assume a simple Iterator
class exists, like this:
python
class Iterator:
def __init__(self, nums):
self.nums = nums
self.index = 0
def hasNext(self):
return self.index < len(self.nums)
def next(self):
val = self.nums[self.index]
self.index += 1
return val
Now we can implement PeekingIterator
:
python
class PeekingIterator:
def __init__(self, iterator: Iterator):
self.iterator = iterator
self.peeked = None
if self.iterator.hasNext():
self.peeked = self.iterator.next()
def peek(self) -> int:
return self.peeked
def next(self) -> int:
val = self.peeked
self.peeked = self.iterator.next() if self.iterator.hasNext() else None
return val
def hasNext(self) -> bool:
return self.peeked is not None
🧪 How It Works
Example: [1, 2, 3]
- Initialize:
peeked = 1
peek()
→ returns 1
, doesn't move
next()
→ returns 1
, updates peeked = 2
next()
→ returns 2
, updates peeked = 3
peek()
→ returns 3
next()
→ returns 3
, peeked = None
hasNext()
→ False
⏱️ Time and Space Complexity
OperationTime ComplexitySpace Complexitypeek()
O(1)O(1)next()
O(1)O(1)hasNext()
O(1)O(1)
🔍 Key Concepts
- Lookahead Caching: This problem demonstrates a key design pattern of caching or lookahead buffering.
- Wrapper Pattern: We’re wrapping an existing object (iterator) to extend its functionality.
- Behavioral Design Pattern: It’s a classic example of enhancing behavior dynamically.
✅ Conclusion
LeetCode 284: Peeking Iterator is a neat design problem that tests your ability to wrap and extend existing functionality. It also introduces important software design ideas like:
- Lookahead buffering
- Object wrapping and method overriding
- API enhancement