Редакция для Число вхождений максимума
Submitting an official solution before solving the problem yourself is a bannable offence.
Автор:
1. Идея
Нужно узнать, сколько раз в массиве встречается его максимальный элемент.
Самый прямой путь: идти по массиву слева направо и поддерживать две величины:
mx— текущий максимальный балл среди уже просмотренных;cnt— сколько раз этот максимум встретился.
Когда читаем очередное число:
- если оно больше
mx, найден новый максимум, значит:- обновляем
mx, - сбрасываем
cntв1;
- обновляем
- если оно равно
mx, просто увеличиваемcnt; - если оно меньше
mx, ничего делать не нужно.
В конце cnt и будет ответом.
2. Наблюдения
Не нужно хранить никакую сложную информацию о массиве. Для ответа достаточно знать только текущий максимум и число его вхождений.
Если встретилось число больше текущего максимума, все прежние подсчёты уже не важны: старый максимум перестаёт быть максимальным, поэтому счётчик нужно начать заново.
Если очередное число равно текущему максимуму, это ещё одно вхождение максимума, значит
cntувеличивается на1.Ограничение
n <= 2 * 10^5легко позволяет пройти по массиву один раз.
3. Алгоритм
- Считать
n. - Считать массив из
nчисел. - Инициализировать:
mx = a[0]cnt = 1
- Для каждого элемента массива, начиная со второго:
- если
a[i] > mx:mx = a[i]cnt = 1
- иначе если
a[i] == mx:cnt += 1
- если
- Вывести
cnt.
4. Почему это работает
Докажем, что после обработки первых i элементов:
mxравен максимуму среди этихiэлементов;cntравен числу вхождений этого максимума среди этихiэлементов.
База
После чтения первого элемента:
- максимум среди одного элемента — это сам первый элемент;
- число его вхождений равно
1.
Значит, изначально всё верно.
Переход
Пусть после обработки некоторой части массива утверждение верно. Рассмотрим следующий элемент x.
Случай 1: x > mx
Тогда новый максимум всей просмотренной части — это x.
Он встретился пока только один раз, значит нужно сделать:
mx = xcnt = 1
Это правильно.
Случай 2: x == mx
Максимум не изменился, но встретился ещё один такой элемент.
Значит число его вхождений увеличивается на 1.
Это тоже правильно.
Случай 3: x < mx
Максимум не изменился и число его вхождений тоже не изменилось.
И это правильно.
Во всех случаях после обработки очередного элемента инвариант сохраняется. Значит, после обработки всего массива cnt действительно равно количеству вхождений максимального элемента.
5. Сложность
- Время:
O(n), потому что каждый элемент рассматривается один раз. - Память:
- для приведённого решения на C++ —
O(1), так как числа можно обрабатывать по мере чтения; - для приведённого решения на Python —
O(n), так как массив считывается целиком в список.
- для приведённого решения на C++ —
6. Код на C++17
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
long long x;
cin >> x;
long long mx = x;
int cnt = 1;
for (int i = 1; i < n; i++) {
cin >> x;
if (x > mx) {
mx = x;
cnt = 1;
} else if (x == mx) {
cnt++;
}
}
cout << cnt << "\n";
return 0;
}
7. Код на Python 3
n = int(input())
a = list(map(int, input().split()))
mx = a[0]
cnt = 1
for i in range(1, n):
if a[i] > mx:
mx = a[i]
cnt = 1
elif a[i] == mx:
cnt += 1
print(cnt)
Комментарии