Saturday, June 25, 2016

284. Peeking Iterator

This is a good problem to evaluate C++ knowledge.
A derived class can inherit public and protected member from base class except private member.
In this problem, PeekingIterator constructor calls Iterator constructor to store and initialize data. All the data will be stored in private member "data" of Iterator so I don't have to create a new member to hold the data but simply call the API from the base class.
To call the public member of base class, I need to use base::public_member.

1:  class PeekingIterator : public Iterator {  
2:  // Below is the interface for Iterator, which is already defined for you.  
3:  // **DO NOT** modify the interface for Iterator.  
4:      lass Iterator {  
5:    struct Data;  
6:        Data* data;  
7:  public:  
8:      Iterator(const vector<int>& nums);  
9:      Iterator(const Iterator& iter);  
10:      virtual ~Iterator();  
11:      // Returns the next element in the iteration.  
12:      int next();  
13:      // Returns true if the iteration has more elements.  
14:      bool hasNext() const;  
15:  };  
16:  public:  
17:      PeekingIterator(const vector<int>& nums) : Iterator(nums) {  
18:        // Initialize any member here.  
19:        // **DO NOT** save a copy of nums and manipulate it directly.  
20:        // You should only use the Iterator interface methods.  
21:      }  
22:    // Returns the next element in the iteration without advancing the iterator.  
23:      int peek() {  
24:      return Iterator(*this).next();  
25:      }  
26:      // hasNext() and next() should behave the same as in the Iterator interface.  
27:      // Override them if needed.  
28:      int next() {  
29:        return Iterator::next();  
30:      }  
31:      bool hasNext() const {  
32:        return Iterator::hasNext();  
33:      }  
34:  };  

When I revisited the code and found the solution above is actually not a good one in interview. Here is how Google Guava does.

1:  // Below is the interface for Iterator, which is already defined for you.  
2:  // **DO NOT** modify the interface for Iterator.  
3:  class Iterator {  
4:    struct Data;  
5:      Data* data;  
6:  public:  
7:      Iterator(const vector<int>& nums);  
8:      Iterator(const Iterator& iter);  
9:      virtual ~Iterator();  
10:      // Returns the next element in the iteration.  
11:      int next();  
12:      // Returns true if the iteration has more elements.  
13:      bool hasNext() const;  
14:  };  
15:  class PeekingIterator : public Iterator {  
16:  private:  
17:    bool peeked;  
18:    int peekedElement;  
19:  public:  
20:      PeekingIterator(const vector<int>& nums) : Iterator(nums) {  
21:        // Initialize any member here.  
22:        // **DO NOT** save a copy of nums and manipulate it directly.  
23:        // You should only use the Iterator interface methods.  
24:        peeked = false;  
25:      }  
26:    // Returns the next element in the iteration without advancing the iterator.  
27:      int peek() {  
28:      peekedElement = peeked ? peekedElement : Iterator::next();  
29:      peeked = true;  
30:      return peekedElement;  
31:      }  
32:      // hasNext() and next() should behave the same as in the Iterator interface.  
33:      // Override them if needed.  
34:      int next() {  
35:        peekedElement = peeked ? peekedElement : Iterator::next();  
36:        peeked = false;  
37:        return peekedElement;  
38:      }  
39:      bool hasNext() const {  
40:        return peeked || Iterator::hasNext();  
41:      }  
42:  };  

No comments:

Post a Comment