A geração da n-ésima combinação é chamada de algoritmo "sem classificação". Observe que permutações e combinações geralmente podem ser equiparadas pela maneira como o problema é parametrizado. Sem saber exatamente qual é o problema, é difícil recomendar a abordagem exata exata e, de fato, para a maioria dos problemas combinatórios, geralmente existem vários algoritmos diferentes de classificação / desarticulação possíveis.
Um bom recurso é "Algoritmos Combinatórios", de Kreher e Stinson. Este livro tem muitos bons algoritmos de classificação e desclassificação claramente explicados. Existem recursos mais avançados, mas eu recomendaria o Kreher como ponto de partida. Como exemplo de um algoritmo de desclassificação, considere o seguinte:
/** PKSUL : permutation given its rank, the slots and the total number of items
* A combinatorial ranking is number of the permutation when sorted in lexicographical order
* Example: given the set { 1, 2, 3, 4 } the ctItems is 4, if the slot count is 3 we have:
* 1: 123 7: 213 13: 312 19: 412
* 2: 124 8: 214 14: 314 20: 413
* 3: 132 9: 231 15: 321 21: 421
* 4: 134 10: 234 16: 324 22: 423
* 5: 142 11: 241 17: 341 23: 431
* 6: 143 12: 243 18: 342 24: 432
* From this we can see that the rank of { 2, 4, 1 } is 11, for example. To unrank the value of 11:
* unrank( 11 ) = { 11 % (slots - digit_place)!, unrank( remainder ) }
* @param rank the one-based rank of the permutation
* @param ctItems the total number of items in the set
* @param ctSlots the number of slots into which the permuations are generated
* @param zOneBased whether the permutation array is one-based or zero-based
* @return zero- or one-based array containing the permutation out of the set { ctItems, 1,...,ctItems }
*/
public static int[] pksul( final int rank, final int ctItems, final int ctSlots, boolean zOneBased ){
if( ctSlots <= 0 || ctItems <= 0 || rank <= 0 ) return null;
long iFactorial = factorial_long( ctItems - 1 ) / factorial_long( ctItems - ctSlots );
int lenPermutation = zOneBased ? ctSlots + 1 : ctSlots;
int[] permutation = new int[ lenPermutation ];
int[] listItemsRemaining = new int[ ctItems + 1 ];
for( int xItem = 1; xItem <= ctItems; xItem++ ) listItemsRemaining[xItem] = xItem;
int iRemainder = rank - 1;
int xSlot = 1;
while( true ){
int iOrder = (int)( iRemainder / iFactorial ) + 1;
iRemainder = (int)( iRemainder % iFactorial );
int iPlaceValue = listItemsRemaining[ iOrder ];
if( zOneBased ){
permutation[xSlot] = iPlaceValue;
} else {
permutation[xSlot - 1] = iPlaceValue;
}
for( int xItem = iOrder; xItem < ctItems; xItem++ ) listItemsRemaining[xItem] = listItemsRemaining[xItem + 1]; // shift remaining items to the left
if( xSlot == ctSlots ) break;
iFactorial /= ( ctItems - xSlot );
xSlot++;
}
if( zOneBased ) permutation[0] = ctSlots;
return permutation;
}
Isso é desregulamentação da permutação, mas, como mencionado acima, em muitos casos, você pode converter uma desorganização da combinação em um problema de permutação equivalente.