← Static tasks

284. Peeking Iterator

leetcode medium

#array#csharp#design#leetcode#medium

Task

Создайте итератор, который поддерживает операцию peek (просмотр следующего элемента) на существующем итераторе, помимо операций hasNext (проверка наличия следующего элемента) и next (получение следующего элемента).

Реализуйте класс PeekingIterator:

PeekingIterator(Iterator<int> nums): Инициализирует объект с заданным итератором целых чисел.

int next(): Возвращает следующий элемент в массиве и перемещает указатель на следующий элемент.

boolean hasNext(): Возвращает true, если в массиве еще есть элементы.

int peek(): Возвращает следующий элемент в массиве без перемещения указателя.

Пример:

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

C# solution

matched/original
using System;
using System.Collections.Generic;
public class PeekingIterator {
    private IEnumerator<int> iterator;
    private bool hasPeeked;
    private int peekedElement;
    public PeekingIterator(IEnumerator<int> iterator) {
        this.iterator = iterator;
    }
    public int Next() {
        if (hasPeeked) {
            hasPeeked = false;
            return peekedElement;
        }
        return iterator.MoveNext() ? iterator.Current : throw new InvalidOperationException();
    }
    public bool HasNext() {
        return hasPeeked || iterator.MoveNext();
    }
    public int Peek() {
        if (!hasPeeked) {
            hasPeeked = iterator.MoveNext();
            peekedElement = iterator.Current;
        }
        return peekedElement;
    }
}

C++ solution

auto-draft, review before submit
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
public class PeekingIterator {
    private IEnumerator<int> iterator;
    private bool hasPeeked;
    private int peekedElement;
    public PeekingIterator(IEnumerator<int> iterator) {
        this.iterator = iterator;
    }
    public int Next() {
        if (hasPeeked) {
            hasPeeked = false;
            return peekedElement;
        }
        return iterator.MoveNext() ? iterator.Current : throw new InvalidOperationException();
    }
    public bool HasNext() {
        return hasPeeked || iterator.MoveNext();
    }
    public int Peek() {
        if (!hasPeeked) {
            hasPeeked = iterator.MoveNext();
            peekedElement = iterator.Current;
        }
        return peekedElement;
    }
}

Java solution

matched/original
import java.util.Iterator;
import java.util.NoSuchElementException;

class PeekingIterator implements Iterator<Integer> {

    private Iterator<Integer> iter;
    private Integer next = null;

    public PeekingIterator(Iterator<Integer> iterator) {
        if (iterator.hasNext()) {
            next = iterator.next();
        }
        iter = iterator;
    }

    public Integer peek() {
        return next;
    }

    @Override
    public Integer next() {
        if (next == null) {
            throw new NoSuchElementException();
        }
        Integer toReturn = next;
        next = null;
        if (iter.hasNext()) {
            next = iter.next();
        }
        return toReturn;
    }

    @Override
    public boolean hasNext() {
        return next != null;
    }
}

JavaScript solution

matched/original
class PeekingIterator {
    constructor(iterator) {
        this.iterator = iterator;
        this.nextElement = iterator.hasNext() ? iterator.next() : null;
    }

    next() {
        const currentElement = this.nextElement;
        this.nextElement = this.iterator.hasNext() ? this.iterator.next() : null;
        return currentElement;
    }

    hasNext() {
        return this.nextElement !== null;
    }

    peek() {
        return this.nextElement;
    }
}

Python solution

matched/original
class PeekingIterator:
    def __init__(self, iterator):
        self.iterator = iterator
        self.next_element = next(iterator, None)

    def next(self):
        current_element = self.next_element
        self.next_element = next(self.iterator, None)
        return current_element

    def hasNext(self):
        return self.next_element is not None

    def peek(self):
        return self.next_element

Go solution

matched/original
type PeekingIterator struct {
    iterator  Iterator
    nextElem  *int
}

func Constructor(iter Iterator) *PeekingIterator {
    var next *int
    if iter.HasNext() {
        val := iter.Next()
        next = &val
    }
    return &PeekingIterator{iterator: iter, nextElem: next}
}

func (this *PeekingIterator) hasNext() bool {
    return this.nextElem != nil
}

func (this *PeekingIterator) next() int {
    current := *this.nextElem
    if this.iterator.HasNext() {
        val := this.iterator.Next()
        this.nextElem = &val
    } else {
        this.nextElem = nil
    }
    return current
}

func (this *PeekingIterator) peek() int {
    return *this.nextElem
}

Explanation

Algorithm

Инициализация итератора:

В конструкторе класса PeekingIterator инициализируйте итератор и проверьте, есть ли следующий элемент. Если есть, установите его как next, иначе установите next в null.

Операция peek:

Метод peek возвращает значение next, не перемещая указатель итератора.

Операции next и hasNext:

Метод next возвращает текущее значение next, обновляет next к следующему элементу в итераторе и перемещает указатель итератора. Если нет следующего элемента, бросает исключение NoSuchElementException.

Метод hasNext возвращает true, если next не равно null, и false в противном случае.

😎