Как алгоритмически работают лексикографические перестановки?

или, например, если вам дано «abcd», лексикографические перестановки будут такими:

abcd
abdc 
acbd
acdb 
adbc 
adcb
bacd
badc
bcad
bcda
bdac
bdca
cabd
cadb
cbad
cbda
cdab
cdba
dabc
dacb
dbac
dbca
dcab
dcba

Я интуитивно понимаю, как это должно быть отсортировано, и если бы вы дали мне любой набор букв или цифр, я мог бы понять, как их следует сортировать, но не математически, как вы будете переходить от одного шага к другому. Например: какой математический процесс приводит вас от abdc к acbd?


person entropy    schedule 19.07.2013    source источник
comment
Эта проблема называется следующей перестановкой, и ответ на нее здесь «алгоритм поиска следующей большей перестановки заданной строки»> stackoverflow.com/questions/1622532/   -  person pkacprzak    schedule 20.07.2013


Ответы (2)


Ну, один из вариантов может быть:

переходить от одного шага к другому,

  • Пусть р = п-1
  • you take (p)th letter abdc => d.
    • you take next letter according to your order.
      • if it exists, then you write it, then end your word with remaining letters ordered
      • иначе p = p - 1, и вы возвращаетесь к предыдущему шагу.

Не уверен, что это лучший способ сделать. Почему хочется переходить от одного шага к другому? почему бы не написать все слова, начиная с написания (n-1)! слова, начинающиеся с первой буквы, затем (n -1)! на секунду...

a
a
...
a
b
b
...
b

для каждого из этих слов: продолжить (n-2)! со второй буквой и (n-2)! с третьей буквы:

ab
ab
...
ab
ac
ac
....
ac
....
ba
ba
...
bc
bc
....

и так далее

person Kek    schedule 19.07.2013
comment
Извините, я думаю, что ваш ответ пролетел мимо меня. Вы проверяете, имеет ли буква справа от текущей буквы большее значение? - person entropy; 19.07.2013
comment
Нет : вы берете n-1 => d. Далее d у вас ничего нет, поэтому вы возвращаетесь к n-2 => b. следующий b, у вас есть c. так что ваше слово начинается с ac. затем остаются b и d, вы просто заказываете их: acbd. - person Kek; 19.07.2013

Если бы английский был моим родным языком, я мог бы объяснить вам каждый аспект этой проблемы. Теперь просто дайте мой код (он сам себя объясняет) для перестановки целого числа:

const int maxn = 2000;
int x[maxn];
void next_permutation(int n)
{
    int i;
    int min_suffix = INT_MAX;
    int min_index = -1;
    for(i=n-1; i>0; --i){
        if(x[i] < x[i+1])break;
    }
    if(i==0){
        for(int i=1; i<=n; ++i){
            x[i] = i;
        }
        return;
    }

    for(int j=i+1; j<=n; ++j){
        if(x[j]>x[i] && x[j]<min_suffix){
            min_suffix = x[j];
            min_index = j;
        }
    }
    //swap x[i], x[min_index];
    {
        int tmp = x[i];
        x[i] = x[min_index];
        x[min_index] = tmp;
    }

    //insert_sort x[i+1...n]
    {
        for(int j=i+2; j<=n; ++j){
            int k;
            for(k=j-1; k>=i+1; --k){
                if(x[j]>x[k])break;
            }

            int tmp = x[j];
            for(int l=j-1; l>k; --l){
                x[l+1] = x[l];
            }
            x[k+1] = tmp;
        }
    }

} 
person lulyon    schedule 19.07.2013