251. Peeking Iterator
Design a PeekingIterator that walks an integer array nums front to back. It is constructed with the array and must support three operations:
next()— consume and return the element currently at the front.has_next()— report whether any unconsumed elements remain.peek()— return the element at the front without consuming it, so a laternext()still returns that same value.
peek and next are only ever invoked while at least one element remains; has_next may be called at any time.
Follow-up to think about: could your design still work if the data arrived as a forward-only stream you could read just once, instead of an array you can index?
Example 1:
Input: it = PeekingIterator([1, 2, 3]); it.next(), it.peek(), it.next(), it.next()
Output: 1, 2, 2, 3
Explanation: next consumes the 1. peek reports 2 but leaves it in place, so the following next still returns 2, and the last next returns 3.
Example 2:
Input: it = PeekingIterator([7, 9]); it.peek(), it.peek(), it.next(), it.has_next(), it.next(), it.has_next()
Output: 7, 7, 7, true, 9, false
Explanation: Repeated peeks are idempotent — both report 7 and consume nothing. After next takes the 7, one element remains (true); after the 9 is taken, none do (false).
Constraints:
- 0 ≤ nums.length ≤ 1000
- -10⁹ ≤ nums[i] ≤ 10⁹
- At most 1000 operations are performed in total.
- peek and next are only called while an element remains.
Hints:
The constructor receives the whole array, so keeping the array plus a cursor index answers all three calls in O(1): peek reads at the cursor, next reads and advances it, hasNext compares it to the length.
For the stream follow-up: stay one element ahead of the caller. Pull the first element into a one-slot buffer at construction; peek returns the buffer, next returns it and refills from the stream, hasNext checks whether the buffer is full.
▶ Run checks these sample cases. Submit also runs hidden edge cases.
Input: nums = [1, 2, 3]; ops = next, peek, next, next
Expected output: 1, 2, 2, 3