Как реализовать функцию компрессии строки с подсчетом повторяющихся символов
Что проверяют
Работу со строками в Go: байты против рун, strings.Builder и аккуратность с граничными случаями. Следом просят уточнить формат вывода, вернуть исходную строку, если сжатие не дало выигрыша, или написать обратную функцию распаковки.
Как отвечать
Сначала задайте вопросы: писать ли счётчик у одиночных символов (a3b1c1 или a3bc), бывают ли во входе символы вне ASCII, бывают ли цифры. С цифрами формат a11 при распаковке становится неоднозначным.
Алгоритм: один проход, храним текущий символ и счётчик. При смене символа дописываем пару в буфер и сбрасываем счётчик, после цикла дописываем последнюю группу. Время O(n), память O(n) под результат.
Что важно именно в Go:
- руны:
stringэто последовательность байт в UTF-8, иs[i]возвращает байт. Для кириллицы и эмодзи идут цикломfor _, r := range s, он декодирует руны, либо переводят строку в[]rune; - буфер:
strings.Builderс заранее вызваннымGrow(len(s)), символы пишутся черезWriteRune; - число:
strconv.Itoa(count)вместоfmt.Sprintf. Он быстрее и не разбирает строку формата на каждой группе; - выигрыш: классическая постановка требует вернуть исходную строку, если сжатая не короче. Длину результата можно посчитать первым проходом и не собирать строку зря.
Тесты оформите табличными: срез структур in и want, прогон через t.Run. Обязательные случаи: пустая строка, один символ, все одинаковые, все разные, кириллица. Если спросят про скорость, покажите бенчмарк: с Go 1.24 его удобно писать через b.Loop().
Где спотыкаются
Идут по байтам. Каждая буква «а» в UTF-8 занимает два байта, соседние байты у неё разные, поэтому строка «ааа» режется на куски и на выходе получается невалидный UTF-8 с неверными счётчиками.
Забывают дописать последнюю группу после цикла или берут s[0] без проверки на пустую строку и получают панику index out of range.
Считают символы через map, как в задаче на частоты. Карта считает все вхождения, а не подряд идущие: для aabaa получится a4b1 вместо a2b1a2, к тому же порядок обхода карты в Go случайный.