Given an Iterator class interface with methods: next()
and hasNext()
, design and implement a PeekingIterator that support the peek()
operation -- it essentially peek() at the element that will be returned by the next call to next().
Example:
Assume that the iterator is initialized to the beginning of the list:[1,2,3]
. Callnext()
gets you 1, the first element in the list. Now you callpeek()
and it returns 2, the next element. Callingnext()
after that still return 2. You callnext()
the final time and it returns 3, the last element. CallinghasNext()
after that should return false.
Hint:
- Think of "looking ahead". You want to cache the next element.
- Is one variable sufficient? Why or why not?
- Test your design with call order of
peek()
beforenext()
vsnext()
beforepeek()
. - For a clean implementation, check out Google's guava library source code.
Follow up: How would you extend your design to be generic and work with all types, not just integer?
這道題讓我們實現一個頂端迭代器,在普通的迭代器類Iterator的基礎上增加了peek的功能,就是返回查看下一個值的功能,但是不移動指針,next()函數才會移動指針,那我們可以定義一個變量專門來保存下一個值,再用一個bool型變量標記是否保存了下一個值,再調用原來的一些成員函數,就可以實現這個頂端迭代器了,參見代碼如下:
解法一:
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) { _flag = false; } int peek() { if (!_flag) _value = Iterator::next(); _flag = true; return _value; } int next() { if (!_flag) return Iterator::next(); _flag = false; return _value; } bool hasNext() const { return _flag || Iterator::hasNext(); } private: int _value; bool _flag; };
這道題主要的考點就是peek函數,因為這個是默認的迭代器不具備的功能。我們其實可以使用一個小trick來實現peek功能,由於peek是要暗中觀察一下下一個元素,但是迭代器並不真正移動到下一個,那么我們其實是可以創建一個副本,然后讓副本移動到下一個,並返回,由於是局部變量,副本在調用結束后也會被銷毀,所以並沒有任何內存問題,可以說是一種相當聰明的解法了,參見代碼如下:
解法二:
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) {} int peek() { return Iterator(*this).next(); } int next() { return Iterator::next(); } bool hasNext() const { return Iterator::hasNext(); } };
類似題目:
參考資料:
https://leetcode.com/problems/peeking-iterator/