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