LeetCode 288: Peeking Iterator (Design / Iterator Wrapper)
LeetCode 288DesignIteratorToday we solve LeetCode 288 - Peeking Iterator.
Source: https://leetcode.com/problems/peeking-iterator/
English
Problem Summary
Wrap an existing iterator so peek() returns the next element without advancing the iterator.
Key Insight
Maintain one cached value nextVal. The cache always represents the next element to return.
Algorithm
Initialize cache with first element if available. peek() returns cache only. next() returns cache and refreshes it from underlying iterator. hasNext() checks whether cache exists.
Complexity
Each operation is O(1) time. Extra space is O(1).
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class PeekingIterator implements Iterator<Integer> {
private final Iterator<Integer> it;
private Integer nextVal;
public PeekingIterator(Iterator<Integer> iterator) {
this.it = iterator;
this.nextVal = it.hasNext() ? it.next() : null;
}
public Integer peek() {
return nextVal;
}
@Override
public Integer next() {
Integer cur = nextVal;
nextVal = it.hasNext() ? it.next() : null;
return cur;
}
@Override
public boolean hasNext() {
return nextVal != null;
}
}type PeekingIterator struct {
data []int
idx int
}
func Constructor(nums []int) PeekingIterator {
return PeekingIterator{data: nums, idx: 0}
}
func (p *PeekingIterator) Peek() int {
return p.data[p.idx]
}
func (p *PeekingIterator) Next() int {
v := p.data[p.idx]
p.idx++
return v
}
func (p *PeekingIterator) HasNext() bool {
return p.idx < len(p.data)
}class PeekingIterator : public Iterator {
private:
bool has_cache;
int cache;
public:
PeekingIterator(const vector<int>& nums) : Iterator(nums) {
has_cache = Iterator::hasNext();
if (has_cache) cache = Iterator::next();
}
int peek() {
return cache;
}
int next() {
int cur = cache;
has_cache = Iterator::hasNext();
if (has_cache) cache = Iterator::next();
return cur;
}
bool hasNext() const {
return has_cache;
}
};class PeekingIterator:
def __init__(self, iterator):
self.it = iterator
self.next_val = self.it.next() if self.it.hasNext() else None
def peek(self):
return self.next_val
def next(self):
cur = self.next_val
self.next_val = self.it.next() if self.it.hasNext() else None
return cur
def hasNext(self):
return self.next_val is not Nonevar PeekingIterator = function(iterator) {
this.it = iterator;
this.nextVal = this.it.hasNext() ? this.it.next() : null;
};
PeekingIterator.prototype.peek = function() {
return this.nextVal;
};
PeekingIterator.prototype.next = function() {
const cur = this.nextVal;
this.nextVal = this.it.hasNext() ? this.it.next() : null;
return cur;
};
PeekingIterator.prototype.hasNext = function() {
return this.nextVal !== null;
};中文
题目概述
对已有迭代器做一层封装,使 peek() 能查看下一个元素但不前进指针。
核心思路
维护一个缓存 nextVal,始终表示“下一次 next() 将返回的值”。
算法步骤
初始化时预取一个元素到缓存;peek() 直接读缓存;next() 返回缓存并从底层迭代器补一个新值;hasNext() 判断缓存是否为空。
复杂度分析
三个操作均为 O(1) 时间,额外空间 O(1)。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class PeekingIterator implements Iterator<Integer> {
private final Iterator<Integer> it;
private Integer nextVal;
public PeekingIterator(Iterator<Integer> iterator) {
this.it = iterator;
this.nextVal = it.hasNext() ? it.next() : null;
}
public Integer peek() {
return nextVal;
}
@Override
public Integer next() {
Integer cur = nextVal;
nextVal = it.hasNext() ? it.next() : null;
return cur;
}
@Override
public boolean hasNext() {
return nextVal != null;
}
}type PeekingIterator struct {
data []int
idx int
}
func Constructor(nums []int) PeekingIterator {
return PeekingIterator{data: nums, idx: 0}
}
func (p *PeekingIterator) Peek() int {
return p.data[p.idx]
}
func (p *PeekingIterator) Next() int {
v := p.data[p.idx]
p.idx++
return v
}
func (p *PeekingIterator) HasNext() bool {
return p.idx < len(p.data)
}class PeekingIterator : public Iterator {
private:
bool has_cache;
int cache;
public:
PeekingIterator(const vector<int>& nums) : Iterator(nums) {
has_cache = Iterator::hasNext();
if (has_cache) cache = Iterator::next();
}
int peek() {
return cache;
}
int next() {
int cur = cache;
has_cache = Iterator::hasNext();
if (has_cache) cache = Iterator::next();
return cur;
}
bool hasNext() const {
return has_cache;
}
};class PeekingIterator:
def __init__(self, iterator):
self.it = iterator
self.next_val = self.it.next() if self.it.hasNext() else None
def peek(self):
return self.next_val
def next(self):
cur = self.next_val
self.next_val = self.it.next() if self.it.hasNext() else None
return cur
def hasNext(self):
return self.next_val is not Nonevar PeekingIterator = function(iterator) {
this.it = iterator;
this.nextVal = this.it.hasNext() ? this.it.next() : null;
};
PeekingIterator.prototype.peek = function() {
return this.nextVal;
};
PeekingIterator.prototype.next = function() {
const cur = this.nextVal;
this.nextVal = this.it.hasNext() ? this.it.next() : null;
return cur;
};
PeekingIterator.prototype.hasNext = function() {
return this.nextVal !== null;
};
Comments