Что такое алгоритм наивного сжатия строки
Что проверяют
Умение написать простой цикл без ошибок на границах и увидеть подвохи задачи. Для Go добавляется свой слой: чем вы обходите строку, байтами или рунами, и чем собираете результат, конкатенацией или билдером.
Как отвечать
Идея проста: идём по строке, считаем длину серии одинаковых символов, на смене символа дописываем сам символ и счётчик. Три подряд идущих a и два b превращаются в a3b2. Обязательное дополнение, ради которого задачу и дают: если результат не короче исходной строки, возвращаем исходную.
func compress(s string) string {
runes := []rune(s)
var b strings.Builder
for i := 0; i < len(runes); {
j := i
for j < len(runes) && runes[j] == runes[i] {
j++
}
b.WriteRune(runes[i])
b.WriteString(strconv.Itoa(j - i))
i = j
}
if b.Len() >= len(s) {
return s
}
return b.String()
}Скажите про стоимость: один проход, время линейное, память под результат линейная. И про формат: схема неоднозначна, если в алфавите встречаются цифры, поэтому в настоящих кодеках серии кодируют иначе, а этот вариант учебный.
Где спотыкаются
Забывают дописать последнюю серию после цикла. Классическая ошибка варианта со сравнением соседей: хвост теряется, потому что смены символа так и не произошло.
Складывают результат плюсом в цикле. Строки в Go неизменяемы, каждая конкатенация выделяет новый буфер, и время становится квадратичным; вопрос закрывает strings.Builder или срез байтов с преобразованием в конце.
Ходят по строке по индексу и ломают всё, что вне ASCII. Индекс строки в Go даёт байт, поэтому кириллица и эмодзи разваливаются на части; нужен обход через range либо преобразование в срез рун.