284. 窥视迭代器
284. 窥视迭代器
题目
Design an iterator that supports the peek operation on an existing iterator in addition to the hasNext and the next operations.
Implement the PeekingIterator class:
PeekingIterator(Iterator<int> nums)Initializes the object with the given integer iteratoriterator.int next()Returns the next element in the array and moves the pointer to the next element.boolean hasNext()Returnstrueif there are still elements in the array.int peek()Returns the next element in the array without moving the pointer.
Note: Each language may have a different implementation of the constructor and Iterator, but they all support the int next() and boolean hasNext() functions.
Example 1:
Input
["PeekingIterator", "next", "peek", "next", "next", "hasNext"]
[[[1, 2, 3]], [], [], [], [], []]
Output
[null, 1, 2, 2, 3, false]
Explanation
PeekingIterator peekingIterator = new PeekingIterator([1, 2, 3]); // [1 ,2,3]
peekingIterator.next(); // return 1, the pointer moves to the next element [1,2 ,3].
peekingIterator.peek(); // return 2, the pointer does not move [1,2 ,3].
peekingIterator.next(); // return 2, the pointer moves to the next element [1,2,3]
peekingIterator.next(); // return 3, the pointer moves to the next element [1,2,3]
peekingIterator.hasNext(); // return False
Constraints:
1 <= nums.length <= 10001 <= nums[i] <= 1000- All the calls to
nextandpeekare valid. - At most
1000calls will be made tonext,hasNext, andpeek.
Follow up: How would you extend your design to be generic and work with all types, not just integer?
题目大意
请你在设计一个迭代器,在集成现有迭代器拥有的 hasNext 和 next 操作的基础上,还额外支持 peek 操作。
实现 PeekingIterator 类:
PeekingIterator(Iterator<int> nums)使用指定整数迭代器nums初始化迭代器。int next()返回数组中的下一个元素,并将指针移动到下个元素处。bool hasNext()如果数组中存在下一个元素,返回true;否则,返回false。int peek()返回数组中的下一个元素,但 不 移动指针。
注意: 每种语言可能有不同的构造函数和迭代器 Iterator,但均支持 int next() 和 boolean hasNext() 函数。
示例 1:
输入:
["PeekingIterator", "next", "peek", "next", "next", "hasNext"]
[[[1, 2, 3]], [], [], [], [], []]
输出:
[null, 1, 2, 2, 3, false]
解释:
PeekingIterator peekingIterator = new PeekingIterator([1, 2, 3]); // [1 ,2,3]
peekingIterator.next(); // 返回 1 ,指针移动到下一个元素 [1,2 ,3]
peekingIterator.peek(); // 返回 2 ,指针未发生移动 [1,2 ,3]
peekingIterator.next(); // 返回 2 ,指针移动到下一个元素 [1,2,3]
peekingIterator.next(); // 返回 3 ,指针移动到下一个元素 [1,2,3]
peekingIterator.hasNext(); // 返回 False
提示:
1 <= nums.length <= 10001 <= nums[i] <= 1000- 对
next和peek的调用均有效 next、hasNext和peek最多调用1000次
进阶: 你将如何拓展你的设计?使之变得通用化,从而适应所有的类型,而不只是整数型?
解题思路
PeekingIterator 是对一个迭代器进行包装,提供额外的 peek() 功能,用于预览下一个元素而不移动迭代器的当前位置。实现过程中,需要维护一个缓存变量来存储“预览的值”,以便在调用 peek() 后,实际调用 next() 时返回正确的结果。
缓存机制
- 引入一个私有变量
peeked用于存储调用peek()时预览的值。 - 如果
peeked中有值,说明上一次调用了peek()而未调用next(),这时应直接返回缓存值。
- 引入一个私有变量
三个方法的逻辑
peek()- 如果
peeked中有值,直接返回该值。 - 如果
peeked中为空,调用iterator.next()获取下一个值并存入peeked,然后返回该值。
- 如果
next()- 如果
peeked中有值,说明调用过peek(),返回缓存值并清空peeked。 - 如果
peeked为空,直接调用iterator.next()返回下一个值。
- 如果
hasNext()- 如果
peeked中有值,说明还有预览的元素,返回true。 - 如果
peeked为空,则调用iterator.hasNext()判断底层迭代器是否有更多元素。
- 如果
边界条件
peeked的初始值为null,以便区分缓存状态。- 处理
iterator在边界条件(如没有更多元素时)的行为。
复杂度分析
- 时间复杂度:
O(1),peek()、next()和hasNext()的时间复杂度均为O(1),因为每次操作最多涉及缓存或底层迭代器的调用。 - 空间复杂度:
O(1),额外的缓存变量peeked占用常数空间。
代码
class PeekingIterator {
constructor(iterator) {
this.iterator = iterator; // 底层迭代器
this.peeked = null; // 缓存的预览值
}
peek() {
// 如果没有缓存值,获取下一个值并缓存
if (this.peeked === null) {
this.peeked = this.iterator.next();
}
return this.peeked;
}
next() {
// 如果缓存中有值,返回缓存值并清空缓存
if (this.peeked !== null) {
const temp = this.peeked;
this.peeked = null;
return temp;
}
// 如果没有缓存,直接从底层迭代器获取下一个值
return this.iterator.next();
}
hasNext() {
// 如果缓存中有值,则一定有下一个元素
if (this.peeked !== null) {
return true;
}
// 否则检查底层迭代器是否有更多元素
return this.iterator.hasNext();
}
}
相关题目
| 题号 | 标题 | 题解 | 标签 | 难度 | 力扣 |
|---|---|---|---|---|---|
| 173 | 二叉搜索树迭代器 | [✓] | 栈 树 设计 3+ | 🟠 | 🀄️ 🔗 |
| 251 | 展开二维向量 🔒 | 设计 数组 双指针 1+ | 🟠 | 🀄️ 🔗 | |
| 281 | 锯齿迭代器 🔒 | 设计 队列 数组 1+ | 🟠 | 🀄️ 🔗 |
