Перетасовка строки так, чтобы две соседние буквы не были одинаковыми
Я пытался решить эту проблему интервью, которая просит перетасовать строку, чтобы никакие две соседние буквы не были идентичными Например,
ABCC - > ACBC
подход, о котором я думаю, это
1) повторите входную строку и сохраните (букву, частоту) пар некоторые коллекция
2) Теперь создайте строку результата, потянув самую высокую частоту (то есть > 0), которую мы не просто тяни!--1-->
3) Обновление (уменьшение) частоты всякий раз, когда мы тянем букву
4) верните строку результата, если все буквы имеют нулевую частоту
5) ошибка возврата, если у нас осталась только одна буква с частотой больше 1
при таком подходе мы можем сохранить более драгоценные (менее частые) буквы для последнего. Но для этого нам нужна коллекция, которая позволяет нам эффективно запрашивать ключ и в то же время эффективно сортируйте по значениям. Что-то вроде этой будет работать, за исключением того, что нам нужно сохранить коллекцию отсортированной после каждого извлечения письма.
Я предполагаю символы Юникода.
любые идеи о том, что сбор использовать? Или альтернативный подход?
3 ответов
вы можете сортировать буквы по частоте, разделить отсортированный список пополам и построить вывод, взяв буквы из двух половин по очереди. Для этого нужен один сорт.
пример:
- исходная строка:
ACABBACAB
- вид:
AAABBBCC
- Сплит:
AAAB
+BBCC
- комбайнер:
ABABACBC
если количество букв самой высокой частоты превышает половину длины строки, проблема не имеет решения.
Почему бы не использовать две структуры данных: одну для сортировки (например, куча) и одну для извлечения ключа, например, словарь?
принятый ответ может привести к правильному результату, но, скорее всего, не является "правильным" ответом на этот мозговой тизер интервью, ни самым эффективным алгоритмом.
простой ответ - взять предпосылку базового алгоритма сортировки и изменить предикат цикла, чтобы проверить смежность, а не величину. Это гарантирует, что операция "сортировка" является единственным требуемым шагом и (как и все хорошие алгоритмы сортировки) выполняет наименьший объем работы вероятный.
Ниже приведен пример c#, похожий на сортировку вставки для простоты (хотя многие алгоритмы сортировки могут быть аналогично скорректированы):
string NonAdjacencySort(string stringInput)
{
var input = stringInput.ToCharArray();
for(var i = 0; i < input.Length; i++)
{
var j = i;
while(j > 0 && j < input.Length - 1 &&
(input[j+1] == input[j] || input[j-1] == input[j]))
{
var tmp = input[j];
input[j] = input[j-1];
input[j-1] = tmp;
j--;
}
if(input[1] == input[0])
{
var tmp = input[0];
input[0] = input[input.Length-1];
input[input.Length-1] = tmp;
}
}
return new string(input);
}
основным изменением стандартной сортировки вставки является то, что функция должна смотреть вперед и назад, и поэтому должна обернуться к последнему индексу.
конечным моментом является то, что этот тип алгоритма терпит неудачу изящно, обеспечивая результат с наименьшим количеством последовательных символов (сгруппированных в фронт.)