Редакция для Подсчёт частот символов


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

1. Идея

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

После подсчёта остаётся правильно отсортировать ответ:

  • сначала по убыванию количества;
  • если количества равны — по алфавиту.

Так как возможных букв всего 26, удобно хранить их частоты в массиве длины 26.

2. Наблюдения

  1. Строка состоит только из букв az, значит для каждой буквы можно завести отдельную ячейку массива.
  2. Индекс буквы легко получить как c - 'a' в C++ или ord(c) - ord('a') в Python.
  3. После одного прохода по строке у нас будут все частоты.
  4. Выводить нужно не все 26 букв, а только те, у которых частота больше нуля.
  5. Сортировка выполняется по парам:
    • чем больше частота, тем раньше буква должна стоять;
    • при равной частоте раньше идёт буква, которая меньше по алфавиту.

3. Алгоритм

  1. Считать строку s.
  2. Создать массив cnt из 26 нулей.
  3. Пройти по всем символам строки и увеличить соответствующий счётчик.
  4. Сформировать список letters, куда добавить пары (буква, количество) только для букв с положительной частотой.
  5. Отсортировать letters:
    • по убыванию количества;
    • при равенстве — по возрастанию буквы.
  6. Вывести все пары по одной на строке.

4. Почему это работает

После прохода по строке в cnt[i] хранится точное число вхождений буквы с индексом i, то есть буквы a + i. Это верно, потому что каждый символ строки ровно один раз увеличивает счётчик своей буквы.

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

После сортировки:

  • буквы с большей частотой окажутся раньше, потому что сортировка сравнивает их по количеству в обратном порядке;
  • если частоты равны, сортировка сравнивает сами буквы и ставит их в алфавитном порядке.

Значит, итоговый вывод полностью соответствует условию задачи.

5. Сложность

Подсчёт частот занимает O(n), где n — длина строки.

Сортировка выполняется не более чем для 26 букв, поэтому её стоимость равна O(26 log 26), то есть это константа.

Итоговая сложность: O(n).

Дополнительная память:

  • массив из 26 чисел;
  • список не более чем из 26 пар.

Итого по памяти: O(1), если не считать входную строку.

6. Код на C++17

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    string s;
    cin >> s;

    vector<long long> cnt(26, 0);
    for (char c : s) {
        cnt[c - 'a']++;
    }

    vector<pair<char, long long>> letters;
    for (int i = 0; i < 26; i++) {
        if (cnt[i] > 0) {
            letters.push_back({char('a' + i), cnt[i]});
        }
    }

    sort(letters.begin(), letters.end(), [](const pair<char, long long>& x, const pair<char, long long>& y) {
        if (x.second != y.second) return x.second > y.second;
        return x.first < y.first;
    });

    for (const auto& p : letters) {
        cout << p.first << " " << p.second << "\n";
    }

    return 0;
}

7. Код на Python 3

s = input()

cnt = [0] * 26
for c in s:
    cnt[ord(c) - ord('a')] += 1

letters = []
for i in range(26):
    if cnt[i] > 0:
        letters.append((chr(ord('a') + i), cnt[i]))

letters.sort(key=lambda x: (-x[1], x[0]))

for ch, num in letters:
    print(ch, num)

Комментарии

Еще нет ни одного комментария.