← Назад к вопросам

Частота символов в строке

1.7 Middle🔥 201 комментариев
#Теория тестирования

Условие

Напишите функцию, которая подсчитывает частоту каждого символа в строке.

Пример

Вход: "hello" Выход: {"h": 1, "e": 1, "l": 2, "o": 1}

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение задачи "Частота символов в строке"

Для подсчёта частоты символов в строке я реализую функцию, которая принимает строку в качестве входного параметра и возвращает словарь (или аналогичную структуру данных), где ключами являются символы, а значениями — количество их вхождений в строке. Рассмотрю несколько подходов к решению, их плюсы и минусы, а также приведу реализацию на Python.

Основные подходы к решению

  1. Использование словаря (hash map) — классический и наиболее эффективный способ для данной задачи.
  2. Использование collections.Counter — встроенный инструмент Python, который упрощает код.
  3. Использование массива/списка для ASCII символов — подходит, если работа ведётся только с символами из определённого диапазона (например, ASCII).

Реализация на Python

Способ 1: Использование обычного словаря

Этот подход универсален и подходит для любых символов, включая Unicode.

def char_frequency_manual(input_string):
    """
    Подсчитывает частоту символов в строке с использованием словаря.
    
    Args:
        input_string (str): Входная строка.
    
    Returns:
        dict: Словарь с частотами символов.
    """
    frequency = {}
    for char in input_string:
        if char in frequency:
            frequency[char] += 1
        else:
            frequency[char] = 1
    return frequency

# Пример использования
result = char_frequency_manual("hello")
print(result)  # Вывод: {'h': 1, 'e': 1, 'l': 2, 'o': 1}

Плюсы:

  • Понятная логика, подходит для обучения.
  • Работает с любыми типами символов.
  • Временная сложность: O(n), где n — длина строки.
  • Пространственная сложность: O(k), где k — количество уникальных символов.

Минусы:

  • Требуется явная проверка наличия ключа в словаре.

Способ 2: Использование метода get для словаря

Улучшенная версия первого способа, которая сокращает код.

def char_frequency_get(input_string):
    frequency = {}
    for char in input_string:
        frequency[char] = frequency.get(char, 0) + 1
    return frequency

Преимущество: Более лаконичный код без явной проверки условий.

Способ 3: Использование collections.Counter

Самый питоничный и краткий способ, использующий встроенную библиотеку.

from collections import Counter

def char_frequency_counter(input_string):
    return dict(Counter(input_string))

Плюсы:

  • Минимальный код.
  • Высокая производительность, так как Counter оптимизирован.
  • Дополнительные возможности: методы most_common(), арифметические операции.

Минусы:

  • Требует импорта модуля.
  • Менее показателен для понимания алгоритма.

Способ 4: Использование списка для ASCII символов

Если известно, что строка содержит только символы ASCII, можно использовать массив фиксированного размера.

def char_frequency_ascii(input_string):
    # Создаём список из 128 нулей (для стандартной ASCII)
    frequency = [0] * 128
    for char in input_string:
        # Получаем код символа
        code = ord(char)
        if code < 128:  # Проверяем, что символ в диапазоне ASCII
            frequency[code] += 1
    
    # Преобразуем в словарь для наглядности вывода
    result = {}
    for i, count in enumerate(frequency):
        if count > 0:
            result[chr(i)] = count
    return result

Плюсы:

  • Быстрее для строк с большим количеством повторяющихся ASCII символов.
  • Прямой доступ по индексу.

Минусы:

  • Не подходит для Unicode символов.
  • Тратит память на неиспользуемые индексы.

Сравнение подходов

КритерийСловарь (ручной)CounterASCII массив
УниверсальностьВысокаяВысокаяНизкая
ПроизводительностьХорошаяОтличнаяОтличная (только ASCII)
Читаемость кодаСредняяВысокаяНизкая
ПамятьЭффективнаяЭффективнаяФиксированная

Дополнительные соображения

  1. Регистр символов: В зависимости от требований, может потребоваться приведение символов к нижнему или верхнему регистру с помощью str.lower() или str.upper().
  2. Игнорирование пробелов: Иногда нужно исключать пробелы или другие символы из подсчёта.
  3. Сортировка результатов: Для удобства вывода можно отсортировать словарь по ключам или значениям.

Пример с дополнительной обработкой:

def char_frequency_advanced(input_string, case_sensitive=True, ignore_spaces=False):
    frequency = {}
    
    for char in input_string:
        # Обработка регистра
        if not case_sensitive:
            char = char.lower()
        
        # Игнорирование пробелов
        if ignore_spaces and char.isspace():
            continue
        
        # Подсчёт
        frequency[char] = frequency.get(char, 0) + 1
    
    return frequency

Заключение

Для производственного кода на Python я рекомендую использовать collections.Counter за его эффективность и лаконичность. Для образовательных целей лучше подойдёт ручная реализация со словарём, так как она наглядно демонстрирует алгоритм. Важно понимать, какой из подходов лучше соответствует требованиям задачи: если работа ведётся только с ASCII и важна максимальная производительность, можно рассмотреть вариант с массивом. В общем случае словарь или Counter являются наиболее универсальными и практичными решениями.