Peeking Iterator - Complete Solution Guide
Peeking Iterator is LeetCode problem 284, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
Design an iterator that supports the peek operation on an existing iterator in addition to the hasNext and the next operations. Implement the PeekingIterator class: PeekingIterator(Iterator<int> nums) Initializes the object with the given integer iterator iterator . int next() Returns the next element in the array and moves the pointer to the next element. boolean hasNext() Returns true if there are still elements in the array. int peek() Returns the next element in the array without moving the
Detailed Explanation
The problem asks us to design an iterator that extends the functionality of a standard iterator by adding a `peek()` operation. The `peek()` operation allows us to look at the next element without advancing the iterator's position. We need to implement a `PeekingIterator` class that wraps an existing iterator and provides `next()`, `hasNext()`, and `peek()` methods. The constraints state that the input array's length is at most 1000 and its elements are between 1 and 1000 inclusive, calls to `next` and `peek` are always valid, and we can make at most 1000 calls to any of the methods.
Solution Approach
The solution uses a combination of caching and a boolean flag. The constructor initializes the PeekingIterator by taking an existing Iterator. It then tries to fetch the first element using `iterator.next()` and stores it in a `_peeked_element` variable. It also maintains a boolean flag `_has_next` to indicate if there's a next element available. The `peek()` method simply returns the `_peeked_element`. The `next()` method returns the current `_peeked_element`, and then updates the `_peeked_element` by advancing the underlying iterator, if there is one. If there are no more elements after calling `next()`, `_has_next` is set to `false` and the _peeked_element is set to null. The `hasNext()` method returns the value of the `_has_next` flag.
Step-by-Step Algorithm
- Step 1: Constructor - Initialize the PeekingIterator with an existing Iterator. Cache the first element (if it exists) in `_peeked_element` and set the `_has_next` flag accordingly.
- Step 2: peek() - Return the value of the cached `_peeked_element`. This doesn't advance the iterator.
- Step 3: next() - Return the current value of `_peeked_element`. Advance the underlying iterator and update `_peeked_element` and `_has_next` if there are more elements. Handle the case where there are no more elements.
- Step 4: hasNext() - Return the value of the `_has_next` flag, indicating if there are more elements in the iterator.
Key Insights
- Insight 1: The core idea is to cache the next element internally, so `peek()` can return it without changing the iterator's state. `next()` returns the cached element and updates the cache if there's another element available.
- Insight 2: We need to maintain a boolean flag to track if there's a 'peeked' element available or if the iterator is exhausted. This helps optimize the `hasNext()` method.
- Insight 3: Careful handling of edge cases, such as when the iterator is initially empty, is crucial for correctness.
Complexity Analysis
Time Complexity: O(1)
Space Complexity: O(1)
Topics
This problem involves: Array, Design, Iterator.
Companies
Asked at: Google.