1. 程式人生 > >LeetCode[Design]----Peeking Iterator

LeetCode[Design]----Peeking Iterator

Peeking Iterator

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().


Here is an example. Assume that the iterator is initialized to the beginning of the list: [1, 2, 3]

.

Call next() gets you 1, the first element in the list.

Now you call peek() and it returns 2, the next element. Calling next() after that still return 2.

You call next() the final time and it returns 3, the last element. Calling hasNext()

 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.')

在實現了Iterator類後,我們來想一下如何構建 PeekingIterator 類。

首先看下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()