284. Peeking Iterator - cocoder39/coco39_LC GitHub Wiki

284. Peeking Iterator

Method 1: O(1) time and space complexity the trick here is calling next() before it is called by outside. Call next() ahead inside constructor and next()

// Below is the interface for Iterator, which is already defined for you.
// **DO NOT** modify the interface for Iterator.
class Iterator {
    struct Data;
	Data* data;
public:
	Iterator(const vector<int>& nums);
	Iterator(const Iterator& iter);
	virtual ~Iterator();
	// Returns the next element in the iteration.
	int next();
	// Returns true if the iteration has more elements.
	bool hasNext() const;
};


class PeekingIterator : public Iterator {
public:
	PeekingIterator(const vector<int>& nums) : Iterator(nums) {
	    // Initialize any member here.
	    // **DO NOT** save a copy of nums and manipulate it directly.
	    // You should only use the Iterator interface methods.
	    
	    //achieve peek() by calling next() ahead
	    my_hasNext = Iterator::hasNext();
	    if (my_hasNext) 
	        my_next = Iterator::next(); 
	}

    // Returns the next element in the iteration without advancing the iterator.
	int peek() { //return next val without advancing iterrator
        return my_next;
	}

	// hasNext() and next() should behave the same as in the Iterator interface.
	// Override them if needed.
	int next() { //return next val with advancing iterator
	//if stepping into this method
	//then it is guaranteed that current my_next is true
	//return previous val and call next() ahead
	    int t = my_next;
	    my_hasNext = Iterator::hasNext();
	    if (my_hasNext)
	        my_next = Iterator::next();
	    return t;
	}

	bool hasNext() const {
	    return my_hasNext;
	}
private:
    int my_next;
    bool my_hasNext;
};

the trick is inside peek() method where copy constructor is used

  • make a copy first through copy constructor
  • calling next on the copied iterator would not affect original iterator
// Below is the interface for Iterator, which is already defined for you.
// **DO NOT** modify the interface for Iterator.
class Iterator {
    struct Data;
	Data* data;
public:
	Iterator(const vector<int>& nums);
	Iterator(const Iterator& iter);
	virtual ~Iterator();
	// Returns the next element in the iteration.
	int next();
	// Returns true if the iteration has more elements.
	bool hasNext() const;
};


class PeekingIterator : public Iterator {
public:
	PeekingIterator(const vector<int>& nums) : Iterator(nums) {
	    // Initialize any member here.
	    // **DO NOT** save a copy of nums and manipulate it directly.
	    // You should only use the Iterator interface methods.
	    
	}

    // Returns the next element in the iteration without advancing the iterator.
	int peek() {
	    //make a copy first through copy constructor
	    //calling next on the copied iterator would not affect original iterator 
        return Iterator(*this).next(); 
	}

	// hasNext() and next() should behave the same as in the Iterator interface.
	// Override them if needed.
	int next() {
	    return Iterator::next();
	}

	bool hasNext() const {
	    return Iterator::hasNext();
	}
};
⚠️ **GitHub.com Fallback** ⚠️