Peeking Iterator
Given an Iterator class interface with methods:next()
andhasNext()
, design and implement a PeekingIterator that support thepeek()
operation -- it essentially peek() at the element that will be returned by the next call to next().
Here is an 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 thatstillreturn 2.
You callnext()
the final time and it returns 3, the last element. CallinghasNext()
after that should return false.
題目分析:
很多編程語言中都有迭代器:iterator,這些迭代器一般都有next()和hasNext()方法,next()方法是用來返回迭代器中下一個元素值的,hasNext()方法是判斷迭代器中是否含有下一個元素。
但是在這裡,我們需要設計一個PeekingIterator,這個迭代器除了前面說的兩個必備功能外,還有一個叫peek()的方法,peek()方法返回調用next()方法會返回的元素值,即peek()方法能夠得到迭代器的下一個元素值,但是其與next()方法不同,peek()的調用並不改變迭代器中指針位置,即可以多次調用peek()方法,而且能夠返回同樣的元素值,而且peek()方法不影響next()和hasNext()方法的正常使用。這裡,你可以類似的理解peek()相當於棧中top()方法,而next()相當於棧中的pop()方法。
所以,給定一個數組[1, 2, 3],調用next()能夠得到第一個元素1,之後調用peek()能夠得到第二個元素2,之後再調用next()還是能夠得到2,再之後調用next()能夠得到3。此時如果調用hasNext()將得到False的返回值。
實現思路:
我選擇的是Python語言,編輯器中提供了PeekingIterator類的實現接口。然後我發現,整個PeekingIterator類的實現是需要借助Iterator的實現的。因為PeekingIterator類中構造函數參數引入了Iterator,是這樣的:def __init__(self, iterator),所以,PeekingIterator類的幾個函數的實現是建立在Iterator的幾個函數的基礎上的。
好吧,為了成功測試代碼以及能夠Iterator的構成,我們可以先實現出Iterator類。
這是一個簡單的類,迭代器的遍歷是不可回退的,我們只要使用不斷遞增的遍歷指針就可以實現了。
代碼為:
class Iterator(object): def __init__(self, nums): """ Initializes an iterator object to the beginning of a list. :type nums: List[int] """ self.nums = nums self.curpoint = 0 # 迭代器的當前指針位置 def hasNext(self): """ Returns true if the iteration has more elements. :rtype: bool """ if self.curpoint <= len(nums) - 1: return True return False def next(self): """ Returns the next element in the iteration. :rtype: int """ if self.hasNext(): self.curpoint += 1 return self.nums[self.curpoint - 1] else: print('Error, there is no elements in this iterator.')
首先看下peek函數。這個函數能夠訪問迭代器下一個指針指向的值,而且能夠多次調用這個函數返回同一個元素的值。我們可以利用Iterator函數的next方法先返回迭代器下一個指針指向的值,然後peek函數返回這個值。為了能夠多次返回同一個值,我們可以使用一個變量peekval記住這個值,並且使用標記ispeek判斷之前是否調用了peek函數,如果調用了那麼返回peekval,如果不是,那麼返回next方法得到的值,並把返回的值記錄在peekval中,設ispeek為已訪問。
對於next函數。我們要先判斷操作之前是否調用過peek函數,如果調用了那麼本次只能返回peekval值,並設ispeek為未訪問;如果未調用過,那麼調用Iterator的next方法得到迭代器的下一個元素值。
對於hasNext函數。一般直接返回Iterator的hasNext方法的返回值就好,但是如果之前使用了peek函數,而peek函數會調用next函數,在next函數中會移動迭代器下一個指針的位置,這樣會出現在調用peek後,指針已經指向了末尾元素,此時調用Iterator的hasNext方法會返回False,而事實上此時迭代器還是有元素的(因為peek不改變迭代器指針的位置)應該返回True。所以在調用hasNext前需要先判斷之前是否調用過peek函數,如果調用過那麼直接返回True就好了。
PeekingIterator的代碼為:
class PeekingIterator(object): def __init__(self, iterator): """ Initialize your data structure here. :type iterator: Iterator """ self.iterator = iterator self.ispeek = False self.peekval = 0 def peek(self): """ Returns the next element in the iteration without advancing the iterator. :rtype: int """ if self.ispeek is False: self.peekval = self.iterator.next() self.ispeek = True return self.peekval def next(self): """ :rtype: int """ if self.ispeek is True: self.ispeek = False return self.peekval return self.iterator.next() def hasNext(self): """ :rtype: bool """ if self.ispeek is True: return True return self.iterator.hasNext()