Все темы
55

Для каждого дня: когда следующий тёплый?

Tier 1Закрыто

Где применяется

1. Задача

У тебя есть температуры за 8 дней: [73, 74, 75, 71, 69, 72, 76, 73]. Для каждого дня надо узнать, сколько дней ждать, пока станет теплее. В первый день 73, во второй 74, значит ответ для первого дня 1. В третий день 75, и теплее становится только на седьмой день (76), значит ответ 4. Если более тёплого дня так и не будет, ответ 0.

Первый план: от каждого дня идти вперёд, пока не найдётся день теплее. Это работает и даёт верный ответ. Но на длинном ряду это цикл внутри цикла. На 10 000 дней выйдет почти 50 000 000 сравнений (49 995 000, если каждый день холоднее предыдущего). Один и тот же тёплый день будут заново просматривать все дни, которые ждут перед ним.

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

Этот шаг из платной части

Бесплатные шаги в начале курса (их 33) открыты всем: урок, задача и тесты. Этот шаг открывается с полным доступом. Начни с бесплатного аккаунта и бесплатных шагов.

Завести бесплатный аккаунтПосмотреть, что входит
Следующий больший элемент через монотонный стек
nextGreater([2, 7, 3, 1, 5, 4, 8])
nums
2
7
3
1
5
4
8
stack (индексы, которые ещё ждут)
пусто
result
-1
-1
-1
-1
-1
-1
-1

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

Гонка скорости
Следующее большее значение для каждого из одних и тех же 40 замеров

Столбики: 40 замеров, которые постепенно снижаются, поэтому большее значение обычно далеко.

Одна операция: одно сравнение. За каждый кадр все дорожки делают одинаковое число операций, поэтому медленная отстаёт.

Просмотр вправо от каждого числа O(n²)
операций: 0
Монотонный стек O(n)
операций: 0

 

А если чисел больше

Операции для n чисел и примерное время при 100 миллионах простых операций в секунду. Это оценка по тому же счёту, а не замер.

n = 1 000
Просмотр вправо от каждого числа375 тыс. · 3,8 мс
Монотонный стек1 тыс. · меньше 1 мс
n = 100 000
Просмотр вправо от каждого числа3,8 млрд · 38 с
Монотонный стек100 тыс. · 1 мс
n = 10 000 000
Просмотр вправо от каждого числа37,5 трлн · 4,3 дн.
Монотонный стек10 млн · 100 мс

Как узнать

Монотонный стек (Monotonic stack)

Эти слова в условии значат этот паттерн

  • ближайший больший / ближайший меньший элемент
  • сколько дней ждать потепления
  • наибольший прямоугольник в гистограмме
  • сколько воды соберётся между столбиками
  • отрезок/серия, заканчивающаяся первым большим или меньшим значением

Похоже, но не то

  • Стек (Stack (LIFO))

    Обычный стек снимает по вашей команде. Монотонный снимает по сравнению.

  • Монотонный дек (Monotonic deque (sliding window max/min))

    Дек ещё и выбрасывает элементы, выпавшие из окна. Если никто не устаревает, хватит стека.

  • Скользящее окно (переменное) (Sliding window (variable))

    Окно отвечает на вопросы про диапазон. Этот стек отвечает про один граничный элемент.

  • Двоичная куча (Binary heap / priority queue)

    Куча даёт глобальный максимум за O(log n). Стек даёт ближайшего большего соседа за O(1).

  • Сортировка с компаратором (Sort with a custom comparator)

    Сортировка выбрасывает позиции. Вопросы про следующий больший целиком про позиции.

n до 1e5 элементов даёт O(n). Каждый элемент кладут один раз и снимают не больше раза.

На LeetCode

Задачи, где для каждого элемента нужен следующий или предыдущий больший или меньший. Монотонный стек из позиций, которые ещё ждут ответа, отвечает каждой из них один раз.

Мы используем необходимые куки для работы сайта (вход и язык). Если ты согласишься, мы также загрузим Google Analytics, чтобы видеть, какие страницы читают, и Google reCAPTCHA для защиты форм обратной связи и сообщений об ошибке от спама. Политика конфиденциальности