↓ Skip to main content
LeetCode 284: Peeking Iterator

LeetCode 284: Peeking Iterator

·454 words·3 mins· loading · loading ·
Author
Dawn Magnet
Tech enthusiast & daily solver.

Design an iterator that supports a peek operation in addition to hasNext and next.

Implement the PeekingIterator class:

  • PeekingIterator(int[] nums) initializes the iterator with the specified integer array nums.
  • int next() returns the next element in the array and moves the pointer to the following element.
  • bool hasNext() returns true if another element exists in the array; otherwise, it returns false.
  • int peek() returns the next element in the array but does not move the pointer.

 

Example:

Input:
["PeekingIterator", "next", "peek", "next", "next", "hasNext"]
[[[1, 2, 3]], [], [], [], [], []]
Output:
[null, 1, 2, 2, 3, false]

Explanation:
PeekingIterator peekingIterator = new PeekingIterator([1, 2, 3]); // [1,2,3]
peekingIterator.next();    // returns 1 and moves the pointer to the next element [1,2,3]
peekingIterator.peek();    // returns 2 without moving the pointer [1,2,3]
peekingIterator.next();    // returns 2 and moves the pointer to the next element [1,2,3]
peekingIterator.next();    // returns 3 and moves the pointer to the next element [1,2,3]
peekingIterator.hasNext(); // returns False

 

Constraints:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 1000
  • All calls to next and peek are valid.
  • next, hasNext, and peek are called at most 1000 times.

 

Follow-up: How would you extend your design to make it generic so that it works with all types, rather than only integers?

Analysis
#

The main difficulty is that the Iterator data structure provided by the original problem exposes only these two interfaces:

  • int next()
  • bool hasNext()

Our data structure must add a third interface, int peek(), on top of them.

This creates a problem: every call to next() unquestionably moves the iterator forward by one position, while a call to peek() does not.

One straightforward idea is to save a number every time next() is called and use it as the return value for the next call to peek(). However, that approach has a problem.

As Example 1 shows, calling peek() does not move the pointer, but it still retrieves the value of the next element. The challenge is to obtain the next element’s value without moving the pointer, even though next() always moves it.

The approach is to keep the next element’s value in a variable. If peek() is called, return this stored value. If next() is called, return the stored value as well, then update the stored value to the following element.

C++ Code
#

class PeekingIterator : public Iterator {
public:
    PeekingIterator(const vector<int>& nums) : Iterator(nums) {
        flag = Iterator::hasNext();
        if (flag) {
            nextElement = Iterator::next();
        }
    }

    int peek() {
        return nextElement;
    }

    int next() {
        int ret = nextElement;
        flag = Iterator::hasNext();
        if (flag) {
            nextElement = Iterator::next();
        }
        return ret;
    }

    bool hasNext() const {
        return flag;
    }
private:
    int nextElement;
    bool flag;
};