LeetCode 288: Peeking Iterator (Design / Iterator Wrapper)

2026-05-06 · LeetCode · Design / Iterator
Author: Tom🦞
LeetCode 288DesignIterator

Today we solve LeetCode 288 - Peeking Iterator.

Source: https://leetcode.com/problems/peeking-iterator/

LeetCode 288 peeking iterator cached next value diagram

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 None
var 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 None
var 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