题目:顶端迭代器
请你设计一个迭代器,除了支持 hasNext
和 next
操作外,还支持 peek
操作。
实现 PeekingIterator
类:
PeekingIterator(int[] nums)
使用指定整数数组 nums
初始化迭代器。int next()
返回数组中的下一个元素,并将指针移动到下个元素处。bool hasNext()
如果数组中存在下一个元素,返回 true
;否则,返回 false
。int peek()
返回数组中的下一个元素,但 不 移动指针。
示例:
1 | 输入: |
提示:
1 <= nums.length <= 1000
1 <= nums[i] <= 1000
对 next 和 peek 的调用均有效
next、hasNext 和 peek 最多调用 1000 次
进阶:你将如何拓展你的设计?使之变得通用化,从而适应所有的类型,而不只是整数型?
分析:
顶端迭代器需要实现以下三种操作:
next
:返回迭代器的下一个元素,并将指针向后移动一位;
hasNext
:判断迭代器中是否还有剩余的元素;
peek
:返回迭代器的下一个元素,不改变指针。
每种编程语言自带的迭代器可能支持上述一种或多种操作,但是不一定支持上述全部操作。如果编程语言自带的迭代器本身就支持上述操作,可以直接使用,否则需要自定义实现。
- C++中
PeekingIterator
继承父类Iterator
,Iterator
已经实现方法next
和hasNext
,在此我们在PeekingIterator
中主要实现peek
方法即可。我们使用flag
标记迭代器是否还有剩余元素,使用nextElement
存储迭代器的下一个元素。
next
:首先用ret
存储nextElement
表示返回值,flag
保存Iterator
调用hasNext
方法的返回结果,然后将nextElement
向后移动一位,最后返回ret
;
hasNext
:返回flag
;
peek
:由于peek操作不改变指针,因此返回nextElement
。
- C#的
IEnumerator
接口包含属性Current和方法MoveNext
(该方法的返回值类型是bool
,表示是否成功移动到下一个元素),三种操作都需要自定义实现,需要使用flag存储迭代器是否还有剩余的元素。
next
:首先用ret
存储iterator.Current
表示返回值,然后对iterator
调用MoveNext
方法使其向后移动一位并将该方法的结果赋值给flag
,最后返回ret
;
hasNext
:返回flag;
peek
:由于peek
操作不改变指针,因此返回iterator.Current
。
题解:
- C++
1 | class PeekingIterator : public Iterator { |
- C#
1 | class PeekingIterator { |
进阶:
进阶问题
进阶问题要求拓展顶端迭代器的设计,使其适用于所有类型,不局限于整数。
对于动态类型语言如 JavaScript
和 Python
,不需要拓展上述设计。
对于静态类型语言如 Java
、C#
和 C++
,可以通过使用泛型的方式拓展设计,在 PeekingIterator
类中定义泛型,使用时可以用任意类型。
总结:
以前习惯将迭代器当作指针来看到,因为感觉上是大同小异,现在加深了对两者区别的理解:迭代器像是有固定方法的指针,不像指针那么随意,更像是名称所展示的那样包含“迭代”的思想