Массив вместо стека

В этом уроке ты
  • Узнаешь, почему не всегда удобно использовать стек.
  • Научишься заменять стек на более удобные структуры данных.
Недостатки использования стека

Стек — удобная структура данных, но бывают случаи, когда его применение становится неудобным или избыточным.

Из стека в массив

Иногда задача требует вернуть ответ в виде массива, но все необходимые элементы уже находятся в стеке. В этом случае приходится перекладывать элементы из стека в массив:

// В языке JavaScript нет встроенного стека, но полезно знать, 
// что такая проблема встречается в других языках
export function arrayFromStack(stack) {
    // Создаём массив нужного размера
    const result = new Array(stack.length);
    const tempStack = [...stack];
    
    // Заполняем массив с конца, так как
    // доступ в стеке только к последнему элементу
    for (let i = stack.length - 1; i >= 0; i--) {
        result[i] = tempStack.pop();
    }
    return result;
}

Проблема не критичная, но неприятная. Возможно, интервьюер предложит тебе упростить такой код и сделать его более компактным.

Нужны последние N значений

Иногда для принятия решения нужно проверить не один последний элемент, а несколько последних элементов стека. В таком случае приходится извлекать несколько элементов подряд и возвращать их обратно, если условие не выполняется:

// Нужно проверить три последних элемента, и только затем удалять их из стека
int third = stack.Pop();
int second = stack.Pop();
int first = stack.Pop();

if (!(curr == first && curr == second && curr == third))
{
    // Возвращаем элементы обратно, если условие не выполнилось
    stack.Push(first);
    stack.Push(second);
    stack.Push(third);
}

Такой подход увеличивает количество кода и создаёт риск запутаться.

Чем можно заменить стек

Стек можно заменить на следующие структуры данных:

  • Дек (deque)
  • Динамический массив

Дек является хорошей альтернативой, особенно когда нужно проверять несколько последних значений без их удаления. Однако если ответ нужно возвращать в виде массива, всё равно потребуется дополнительное преобразование.

Наиболее универсальным решением является использование динамического массива, так как он:

  • Позволяет удобно возвращать результат сразу в виде массива.
  • Позволяет легко проверить последние N значений без их удаления:
// Проверяем элементы до удаления, избегая лишних операций
if (stack.Count >= 3 && 
    curr == stack.Peek() && 
    curr == stack.ElementAt(stack.Count - 2) && 
    curr == stack.ElementAt(stack.Count - 3)) {
    stack.Pop();
    stack.Pop();
    stack.Pop();
}
Кратко о главном

Вместо стека удобно использовать динамический массив, так как он решает большинство проблем, связанных с извлечением элементов.

Что дальше

Теперь скорее переходи к задачам, чтобы закрепить полученные знания на практике!