Перетасовка строки так, чтобы две соседние буквы не были одинаковыми

Я пытался решить эту проблему интервью, которая просит перетасовать строку, чтобы никакие две соседние буквы не были идентичными Например,

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);
}

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

конечным моментом является то, что этот тип алгоритма терпит неудачу изящно, обеспечивая результат с наименьшим количеством последовательных символов (сгруппированных в фронт.)